-
Notifications
You must be signed in to change notification settings - Fork 2
feat: add capabilities proxy #408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
e8bfec2
dd7dbfa
7328d3f
42c754f
cbb3df6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace MyParcelNL\Pdk\Api; | ||
|
|
||
| /** | ||
| * Constants for capabilities-related actions in the PDK | ||
| */ | ||
| class PdkCapabilitiesActions | ||
| { | ||
| public const PROXY_CAPABILITIES = 'proxyCapabilities'; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace MyParcelNL\Pdk\Api\Response; | ||
|
|
||
| use MyParcelNL\Pdk\Api\Contract\ClientResponseInterface; | ||
| use Symfony\Component\HttpFoundation\Response; | ||
|
|
||
| /** | ||
| * Response for capabilities API requests | ||
| */ | ||
| class CapabilitiesResponse extends ApiResponse | ||
| { | ||
| /** | ||
| * @var null|string | ||
| */ | ||
| private $body; | ||
|
|
||
| /** | ||
| * @var null|int | ||
| */ | ||
| private $statusCode; | ||
|
|
||
| public function __construct(ClientResponseInterface $response) | ||
| { | ||
| parent::__construct($response); | ||
| $this->body = $response->getBody(); | ||
| $this->statusCode = $response->getStatusCode(); | ||
| } | ||
|
|
||
| public function getBody(): ?string | ||
| { | ||
| return $this->body; | ||
| } | ||
|
|
||
| public function getSymfonyResponse(): Response | ||
| { | ||
| return new Response($this->body, $this->statusCode, ['Content-Type' => 'application/json']); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace MyParcelNL\Pdk\Api\Service; | ||
|
|
||
| use MyParcelNL\Pdk\Facade\Pdk; | ||
| use MyParcelNL\Pdk\Facade\Settings; | ||
| use MyParcelNL\Pdk\Settings\Model\AccountSettings; | ||
| use RuntimeException; | ||
|
|
||
| /** | ||
| * Service for communicating with the Capabilities API | ||
| */ | ||
| class CapabilitiesApiService extends AbstractApiService | ||
| { | ||
| /** | ||
| * @return string | ||
| */ | ||
| public function getBaseUrl(): string | ||
| { | ||
| $baseUrl = $this->baseUrl ?? Pdk::get('capabilitiesServiceUrl'); | ||
|
|
||
| if (! $baseUrl) { | ||
| throw new RuntimeException('Capabilities service URL is not configured'); | ||
| } | ||
|
|
||
| return $baseUrl; | ||
| } | ||
|
|
||
| /** | ||
| * @return array | ||
| */ | ||
| public function getHeaders(): array | ||
| { | ||
| $apiKey = Settings::get(AccountSettings::API_KEY, AccountSettings::ID); | ||
|
|
||
| if (! $apiKey) { | ||
| throw new RuntimeException('API key is not configured'); | ||
| } | ||
|
|
||
| return [ | ||
| 'Authorization' => sprintf('bearer %s', base64_encode($apiKey)), | ||
| 'User-Agent' => $this->getUserAgentHeader(), | ||
| ]; | ||
| } | ||
|
|
||
| /** | ||
| * @return string | ||
| */ | ||
| protected function getUserAgentHeader(): string | ||
| { | ||
| $userAgentStrings = []; | ||
| $userAgents = array_merge( | ||
| (array) (Pdk::get('userAgent') ?? []), | ||
| [ | ||
| 'MyParcelNL-PDK' => Pdk::get('pdkVersion'), | ||
| 'php' => PHP_VERSION, | ||
| ] | ||
| ); | ||
|
|
||
| foreach ($userAgents as $platform => $version) { | ||
| if ($version) { | ||
| $userAgentStrings[] = sprintf('%s/%s', $platform, $version); | ||
| } | ||
| } | ||
|
|
||
| return implode(' ', $userAgentStrings); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace MyParcelNL\Pdk\App\Action\Capabilities; | ||
|
|
||
| use MyParcelNL\Pdk\Api\Handler\CorsHandler; | ||
| use MyParcelNL\Pdk\Api\Request\Request as ApiRequest; | ||
| use MyParcelNL\Pdk\Api\Response\CapabilitiesResponse; | ||
| use MyParcelNL\Pdk\Api\Service\CapabilitiesApiService; | ||
| use MyParcelNL\Pdk\App\Action\Contract\ActionInterface; | ||
| use MyParcelNL\Pdk\Facade\Pdk; | ||
| use Symfony\Component\HttpFoundation\Request; | ||
| use Symfony\Component\HttpFoundation\Response; | ||
|
|
||
| class CapabilitiesAction implements ActionInterface | ||
| { | ||
| /** | ||
| * @var \MyParcelNL\Pdk\Api\Service\CapabilitiesApiService | ||
| */ | ||
| private $apiService; | ||
|
|
||
| /** | ||
| * @param \MyParcelNL\Pdk\Api\Service\CapabilitiesApiService $apiService | ||
| */ | ||
| public function __construct(CapabilitiesApiService $apiService) | ||
| { | ||
| $this->apiService = $apiService; | ||
| } | ||
|
|
||
| /** | ||
| * @param \Symfony\Component\HttpFoundation\Request $request | ||
| * | ||
| * @return \Symfony\Component\HttpFoundation\Response | ||
| */ | ||
| public function handle(Request $request): Response | ||
| { | ||
| $corsHandler = Pdk::get(CorsHandler::class); | ||
|
|
||
| if ($request->isMethod('OPTIONS')) { | ||
| return $corsHandler->handlePreflightRequest($request) ?? new Response(); | ||
| } | ||
|
|
||
| /** @var \MyParcelNL\Pdk\Api\Response\CapabilitiesResponse $response */ | ||
| $response = $this->apiService->doRequest($this->buildRequest($request), CapabilitiesResponse::class); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here the SDK capabilities client needs to be used rather than internal PDK API logic (see acceptance criteria) |
||
|
|
||
| $symfonyResponse = $response->getSymfonyResponse(); | ||
|
|
||
| return $corsHandler->addCorsHeaders($request, $symfonyResponse); | ||
| } | ||
|
|
||
| /** | ||
| * @param \Symfony\Component\HttpFoundation\Request $incomingRequest | ||
| * | ||
| * @return \MyParcelNL\Pdk\Api\Request\Request | ||
| */ | ||
| public function buildRequest(Request $incomingRequest): ApiRequest | ||
| { | ||
| $query = $incomingRequest->query->all(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not the correct way to call capabilities - but using the SDK for this should make it redundant |
||
| $path = $query['path'] ?? ''; | ||
| $method = $incomingRequest->getMethod(); | ||
|
|
||
| unset($query['action'], $query['pdk_action'], $query['path']); | ||
|
|
||
| return new ApiRequest([ | ||
| 'method' => $method, | ||
| 'path' => $path ? '/' . ltrim((string) $path, '/') : '', | ||
| 'parameters' => $query, | ||
| ]); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace MyParcelNL\Pdk\App\Request\Capabilities; | ||
|
|
||
| use MyParcelNL\Pdk\App\Request\AbstractEndpointRequest; | ||
|
|
||
| class CapabilitiesEndpointRequest extends AbstractEndpointRequest | ||
| { | ||
| /** | ||
| * @return string | ||
| */ | ||
| public function getProperty(): string | ||
| { | ||
| return 'capabilities'; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Willen we dit echt letterlijk dupliceren uit de MyParcelApiService? Anders zou ik het anders oplossen. Ik zie nu dat de AddressesApiService ook precies dezelfde code heeft. Misschien kan het gewoon in de AbstractApiService gezet worden, dan hebben alle apies het. 🐵