Skip to content

Commit

Permalink
fix: feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
wthijmen committed Nov 6, 2023
1 parent 5708254 commit fcfb8ab
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 14 deletions.
26 changes: 15 additions & 11 deletions src/App/Webhook/PdkWebhookManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,14 @@ public function call($input, string $context = self::CONTEXT_WEBHOOK): Response
*/
public function processWebhook(Request $request): void
{
$logContext = ['request' => get_object_vars($request)];
$requiredPath = parse_url($this->webhooksRepository->getHashedUrl(), PHP_URL_PATH);
$logContext = ['request' => get_object_vars($request)];

if ($request->getRequestUri() !== $requiredPath) {
Logger::error('Webhook received with invalid url', $logContext);

return;
}

Logger::debug('Webhook received', $logContext);

Expand Down Expand Up @@ -117,17 +124,14 @@ protected function resolveHook(string $event): HookInterface
*/
private function getHooks(Request $request): array
{
$headers = $request->headers->all();
$body = json_decode($request->getContent(), true);
$myParcelHeader = $request->headers->get('x-myparcel-hook');
$body = json_decode($request->getContent(), true);
$hooks = $body['data']['hooks'] ?? [];

if (isset($headers['x-myparcel-hook'])) {
$body['data']['hooks'] = array_map(function ($hook) use ($headers) {
$hook['event'] = $headers['x-myparcel-hook'][0];

return $hook;
}, $body['data']['hooks']);
}
return array_map(static function ($hook) use ($myParcelHeader) {
$hook['event'] = $myParcelHeader;

return $body['data']['hooks'] ?? [];
return $hook;
}, $hooks);
}
}
87 changes: 84 additions & 3 deletions tests/Unit/App/Webhook/PdkWebhookManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,93 @@

usesShared(new UsesMockPdkInstance(), new UsesMockEachCron());

it('dispatches incoming webhook', function (string $hook) {
it('dispatches and executes webhooks with myparcel header', function (string $hook) {
/** @var PdkWebhooksRepositoryInterface $repository */
$repository = Pdk::get(PdkWebhooksRepositoryInterface::class);
/** @var PdkWebhookManagerInterface $webhookManager */
$webhookManager = Pdk::get(PdkWebhookManagerInterface::class);
/** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockCronService $cronService */
$cronService = Pdk::get(CronServiceInterface::class);

$repository->storeHashedUrl('https://example.com/hashed-url');

$repository->store(new WebhookSubscriptionCollection([['hook' => $hook, 'url' => $repository->getHashedUrl()]]));

$time = time();

$request = Request::create(
$repository->getHashedUrl(),
Request::METHOD_POST,
[],
[],
[],
['HTTP_X_MYPARCEL_HOOK' => $hook],
json_encode([
'data' => [
'hooks' => [
['event' => $hook],
],
],
])
);

$response = $webhookManager->call($request);

$scheduled = $cronService->getScheduledTasks();
$timestamp = $scheduled->first()['timestamp'];

expect($response->getStatusCode())
->toBe(Response::HTTP_ACCEPTED)
->and($request->headers->all())
->toHaveKey('x-myparcel-hook')
->and($response->getContent())
->toBe('')
->and($response->getStatusCode())
->toBe(Response::HTTP_ACCEPTED)
->and($scheduled->all())
->toHaveLength(1)
// The webhook is scheduled to start immediately. Add a little window to account for the time it takes to run the test.
->and($timestamp)
->toBeGreaterThanOrEqual($time - 10)
->and($timestamp)
->toBeLessThanOrEqual($time + 10);

$cronService->executeAllTasks();
expect(
$cronService->getScheduledTasks()
->all()
)->toBeEmpty();
})->with(WebhookSubscription::ALL);

it('dispatches and executes incoming webhook without myparcel header', function (string $hook) {
/** @var PdkWebhooksRepositoryInterface $repository */
$repository = Pdk::get(PdkWebhooksRepositoryInterface::class);
/** @var PdkWebhookManagerInterface $webhookManager */
$webhookManager = Pdk::get(PdkWebhookManagerInterface::class);
/** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockCronService $cronService */
$cronService = Pdk::get(CronServiceInterface::class);

$repository->storeHashedUrl('https://example.com/hashed-url');
$repository->store(new WebhookSubscriptionCollection([['hook' => $hook, 'url' => $repository->getHashedUrl()]]));

$time = time();
$response = $webhookManager->call(new Request());
$time = time();

$request = Request::create(
$repository->getHashedUrl(),
Request::METHOD_POST,
[],
[],
[],
[],
json_encode([
'data' => [
'hooks' => [
['event' => $hook],
],
],
])
);
$response = $webhookManager->call($request);

$scheduled = $cronService->getScheduledTasks();

Expand All @@ -49,4 +124,10 @@
->toBeGreaterThanOrEqual($time - 10)
->and($timestamp)
->toBeLessThanOrEqual($time + 10);

$cronService->executeAllTasks();
expect(
$cronService->getScheduledTasks()
->all()
)->toBeEmpty();
})->with(WebhookSubscription::ALL);

0 comments on commit fcfb8ab

Please sign in to comment.