CreateShortUrlContentNegotiationMiddleware.php 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <?php
  2. declare(strict_types=1);
  3. namespace Shlinkio\Shlink\Rest\Middleware\ShortUrl;
  4. use Laminas\Diactoros\Response;
  5. use Laminas\Diactoros\Response\JsonResponse;
  6. use Psr\Http\Message\ResponseInterface;
  7. use Psr\Http\Message\ServerRequestInterface;
  8. use Psr\Http\Server\MiddlewareInterface;
  9. use Psr\Http\Server\RequestHandlerInterface;
  10. use function array_shift;
  11. use function explode;
  12. use function strpos;
  13. use function strtolower;
  14. class CreateShortUrlContentNegotiationMiddleware implements MiddlewareInterface
  15. {
  16. private const PLAIN_TEXT = 'text';
  17. private const JSON = 'json';
  18. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
  19. {
  20. $response = $handler->handle($request);
  21. // If the response is not JSON, return it as is
  22. if (! $response instanceof JsonResponse) {
  23. return $response;
  24. }
  25. $query = $request->getQueryParams();
  26. $acceptedType = isset($query['format'])
  27. ? $this->determineAcceptTypeFromQuery($query)
  28. : $this->determineAcceptTypeFromHeader($request->getHeaderLine('Accept'));
  29. // If JSON was requested, return the response from next handler as is
  30. if ($acceptedType === self::JSON) {
  31. return $response;
  32. }
  33. // If requested, return a plain text response containing the short URL only
  34. $resp = (new Response())->withHeader('Content-Type', 'text/plain');
  35. $body = $resp->getBody();
  36. $body->write($this->determineBody($response));
  37. $body->rewind();
  38. return $resp;
  39. }
  40. private function determineAcceptTypeFromQuery(array $query): string
  41. {
  42. if (! isset($query['format'])) {
  43. return self::JSON;
  44. }
  45. $format = strtolower($query['format']);
  46. return $format === 'txt' ? self::PLAIN_TEXT : self::JSON;
  47. }
  48. private function determineAcceptTypeFromHeader(string $acceptValue): string
  49. {
  50. $accepts = explode(',', $acceptValue);
  51. $accept = strtolower(array_shift($accepts));
  52. return strpos($accept, 'text/plain') !== false ? self::PLAIN_TEXT : self::JSON;
  53. }
  54. private function determineBody(JsonResponse $resp): string
  55. {
  56. $payload = $resp->getPayload();
  57. return $payload['shortUrl'] ?? $payload['error'] ?? '';
  58. }
  59. }