Skip to content

Commit b94baa6

Browse files
authored
Refactoring to minimal dependencies + add native support for baraja-core/cas. (#46)
* Native support for baraja-core/cas. * Simplify internal implementation, use native code. * Schema: Remove legacy experiment. * Response: Remove legacy getArray method. * Codestyle formatting. * Remove experimental firewall method. * Tracy is only possible dependecy.
1 parent dc503e6 commit b94baa6

12 files changed

Lines changed: 94 additions & 322 deletions

.phpstorm.meta.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
exitPoint(\Baraja\StructuredApi\BaseEndpoint::sendSuccess());
1010
exitPoint(\Baraja\StructuredApi\BaseEndpoint::sendError());
1111
exitPoint(\Baraja\StructuredApi\BaseEndpoint::sendItems());
12-
exitPoint(\Baraja\StructuredApi\BaseEndpoint::redirect());
13-
exitPoint(\Baraja\StructuredApi\BaseEndpoint::redirectUrl());
1412
exitPoint(\Baraja\StructuredApi\ThrowStatusResponse::invoke());
1513
exitPoint(\Baraja\StructuredApi\Response\Status\StatusResponse::invoke());
1614
exitPoint(\Baraja\StructuredApi\Response\Status\ErrorResponse::invoke());

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
"nette/http": "^3.1",
2121
"nette/application": "^3.1",
2222
"nette/robot-loader": "^3.3",
23-
"nette/caching": "^3.1",
24-
"nette/security": "^3.1"
23+
"nette/caching": "^3.1"
2524
},
2625
"require-dev": {
2726
"phpstan/phpstan": "^1.0",
@@ -31,6 +30,7 @@
3130
"phpstan/phpstan-strict-rules": "^1.0",
3231
"spaze/phpstan-disallowed-calls": "^2.0",
3332
"baraja-core/localization": "^2.0",
33+
"baraja-core/cas": "^1.0",
3434
"tracy/tracy": "^2.8",
3535
"roave/security-advisories": "dev-master"
3636
},

src/ApiManager.php

Lines changed: 25 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Baraja\StructuredApi;
66

77

8+
use Baraja\Localization\Localization;
89
use Baraja\RuntimeInvokeException;
910
use Baraja\Serializer\Serializer;
1011
use Baraja\ServiceMethodInvoker;
@@ -61,26 +62,26 @@ public function __construct(
6162
public function run(?string $path = null, ?array $params = [], ?string $method = null, bool $throw = false): void
6263
{
6364
$path ??= Url::get()->getRelativeUrl();
64-
$this->checkFirewall();
6565
$method = $method === null || $method === '' ? Helpers::httpMethod() : $method;
6666
$params = array_merge($this->safeGetParams($path), $this->getBodyParams($method), $params ?? []);
6767
$panel = new Panel($path, $params, $method);
68-
Debugger::getBar()->addPanel($panel);
68+
$isDebugger = class_exists(Debugger::class);
69+
if ($isDebugger) {
70+
Debugger::getBar()->addPanel($panel);
71+
}
6972

7073
if (preg_match('/^api\/v(?<v>\d{1,3}(?:\.\d{1,3})?)\/(?<path>.*?)$/', $path, $pathParser) === 1) {
7174
try {
7275
$route = $this->route((string) preg_replace('/^(.*?)(\?.*|)$/', '$1', $pathParser['path']), $pathParser['v'], $params);
73-
$response = null;
7476
try {
75-
$endpoint = $this->getEndpointService($route['class'], $params);
77+
$endpoint = $this->getEndpointService($route['class']);
7678
$panel->setEndpoint($endpoint);
7779
$response = $this->process($endpoint, $params, $route['action'], $method, $panel);
7880
$panel->setResponse($response);
7981
} catch (StructuredApiException $e) {
8082
throw $e;
8183
} catch (\Throwable $e) {
82-
$isDebugger = class_exists(Debugger::class);
83-
if ($isDebugger === true) {
84+
if ($isDebugger) {
8485
Debugger::log($e, ILogger::EXCEPTION);
8586
}
8687

@@ -149,39 +150,14 @@ public function getEndpoints(): array
149150
* Create new API endpoint instance with all injected dependencies.
150151
*
151152
* @param class-string $className
152-
* @param array<string|int, mixed> $params
153153
* @internal
154154
*/
155-
public function getEndpointService(string $className, array $params): Endpoint
155+
public function getEndpointService(string $className): Endpoint
156156
{
157157
$endpoint = $this->container->getEndpoint($className);
158-
$endpoint->setConvention($this->convention);
159-
160-
$createReflection = static function (object $class, string $propertyName): ?\ReflectionProperty {
161-
try {
162-
$ref = new \ReflectionProperty($class, $propertyName);
163-
$ref->setAccessible(true);
164-
165-
return $ref;
166-
} catch (\ReflectionException) {
167-
$refClass = new \ReflectionClass($class);
168-
$parentClass = $refClass->getParentClass();
169-
while ($parentClass !== false) {
170-
try {
171-
$ref = $parentClass->getProperty($propertyName);
172-
$ref->setAccessible(true);
173-
174-
return $ref;
175-
} catch (\ReflectionException) {
176-
$parentClass = $refClass->getParentClass();
177-
}
178-
}
179-
}
180-
181-
return null;
182-
};
183-
184-
$createReflection($endpoint, 'data')?->setValue($endpoint, $params);
158+
if ($endpoint instanceof BaseEndpoint) {
159+
$endpoint->convention = $this->convention;
160+
}
185161

186162
return $endpoint;
187163
}
@@ -336,8 +312,17 @@ private function invokeActionMethod(
336312
array $params,
337313
Panel $panel,
338314
): ?Response {
339-
$endpoint->startup();
340-
$endpoint->startupCheck();
315+
if (PHP_SAPI !== 'cli') {
316+
$httpRequest = class_exists(Request::class)
317+
? $this->container->getByType(Request::class)
318+
: null;
319+
$localization = class_exists(Localization::class)
320+
? $this->container->getByType(Localization::class)
321+
: null;
322+
if ($httpRequest !== null && $localization !== null) {
323+
$localization->processHttpRequest($httpRequest);
324+
}
325+
}
341326

342327
try {
343328
$invoker = new ServiceMethodInvoker($this->projectEntityRepository);
@@ -381,8 +366,9 @@ private function invokeActionMethod(
381366
if ($method !== 'GET' && $response === null) {
382367
$response = new JsonResponse($this->convention, ['state' => 'ok']);
383368
}
384-
385-
$endpoint->saveState();
369+
if ($endpoint instanceof BaseEndpoint) {
370+
$endpoint->saveState();
371+
}
386372

387373
return $response;
388374
}
@@ -432,19 +418,6 @@ private function getBodyParams(string $method): array
432418
}
433419

434420

435-
private function checkFirewall(): void
436-
{
437-
if (str_contains($_SERVER['HTTP_USER_AGENT'] ?? '', 'CloudFlare-AlwaysOnline') === true) {
438-
header('HTTP/1.0 403 Forbidden');
439-
echo '<title>Access denied | API endpoint</title>';
440-
echo '<h1>Access denied</h1>';
441-
echo '<p>API endpoint crawling is disabled for robots.</p>';
442-
echo '<p><b>Information for developers:</b> Endpoint API indexing is disabled for privacy reasons. At the same time, robots can crawl a disproportionate amount of data, copying your valuable data.';
443-
die;
444-
}
445-
}
446-
447-
448421
private function rewriteInvalidArgumentException(\InvalidArgumentException $e): ?Response
449422
{
450423
$message = null;

src/Bridge/LinkGeneratorBridge.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Baraja\StructuredApi\Bridge;
6+
7+
8+
use Nette\Application\LinkGenerator;
9+
10+
final class LinkGeneratorBridge
11+
{
12+
public function __construct(
13+
private ?LinkGenerator $linkGenerator = null,
14+
) {
15+
}
16+
17+
18+
/**
19+
* Generates URL to presenter.
20+
*
21+
* @param string $dest in format "[[[module:]presenter:]action] [#fragment]"
22+
* @param array<string, mixed> $params
23+
* @throws \InvalidArgumentException
24+
*/
25+
public function link(string $dest, array $params = []): string
26+
{
27+
if ($this->linkGenerator === null) {
28+
throw new \RuntimeException('Service LinkGenerator is not available. Did you install nette/application?');
29+
}
30+
31+
try {
32+
return $this->linkGenerator->link(ltrim($dest, ':'), $params);
33+
} catch (\Throwable $e) {
34+
throw new \InvalidArgumentException($e->getMessage(), $e->getCode());
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)