mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-03 20:20:38 -06:00
Merge pull request #719 from acelaya-forks/feature/handle-HEAD-requests
Feature/handle head requests
This commit is contained in:
commit
f79a369884
@ -25,6 +25,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
|
|||||||
#### Fixed
|
#### Fixed
|
||||||
|
|
||||||
* [#712](https://github.com/shlinkio/shlink/issues/712) Fixed app set-up not clearing entities metadata cache.
|
* [#712](https://github.com/shlinkio/shlink/issues/712) Fixed app set-up not clearing entities metadata cache.
|
||||||
|
* [#711](https://github.com/shlinkio/shlink/issues/711) Fixed `HEAD` requests returning a duplicated `Content-Length` header.
|
||||||
|
* [#716](https://github.com/shlinkio/shlink/issues/716) Fixed Twitter not properly displaying preview for final long URL.
|
||||||
|
|
||||||
|
|
||||||
## 2.1.2 - 2020-03-29
|
## 2.1.2 - 2020-03-29
|
||||||
|
@ -5,8 +5,9 @@ declare(strict_types=1);
|
|||||||
namespace Shlinkio\Shlink;
|
namespace Shlinkio\Shlink;
|
||||||
|
|
||||||
use Laminas\Stratigility\Middleware\ErrorHandler;
|
use Laminas\Stratigility\Middleware\ErrorHandler;
|
||||||
use Mezzio;
|
use Mezzio\Helper;
|
||||||
use Mezzio\ProblemDetails;
|
use Mezzio\ProblemDetails;
|
||||||
|
use Mezzio\Router;
|
||||||
use PhpMiddleware\RequestId\RequestIdMiddleware;
|
use PhpMiddleware\RequestId\RequestIdMiddleware;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -14,7 +15,7 @@ return [
|
|||||||
'middleware_pipeline' => [
|
'middleware_pipeline' => [
|
||||||
'error-handler' => [
|
'error-handler' => [
|
||||||
'middleware' => [
|
'middleware' => [
|
||||||
Mezzio\Helper\ContentLengthMiddleware::class,
|
Helper\ContentLengthMiddleware::class,
|
||||||
ErrorHandler::class,
|
ErrorHandler::class,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -35,14 +36,15 @@ return [
|
|||||||
|
|
||||||
'routing' => [
|
'routing' => [
|
||||||
'middleware' => [
|
'middleware' => [
|
||||||
Mezzio\Router\Middleware\RouteMiddleware::class,
|
Router\Middleware\RouteMiddleware::class,
|
||||||
|
Router\Middleware\ImplicitHeadMiddleware::class,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
'rest' => [
|
'rest' => [
|
||||||
'path' => '/rest',
|
'path' => '/rest',
|
||||||
'middleware' => [
|
'middleware' => [
|
||||||
Mezzio\Router\Middleware\ImplicitOptionsMiddleware::class,
|
Router\Middleware\ImplicitOptionsMiddleware::class,
|
||||||
Rest\Middleware\BodyParserMiddleware::class,
|
Rest\Middleware\BodyParserMiddleware::class,
|
||||||
Rest\Middleware\AuthenticationMiddleware::class,
|
Rest\Middleware\AuthenticationMiddleware::class,
|
||||||
],
|
],
|
||||||
@ -50,7 +52,7 @@ return [
|
|||||||
|
|
||||||
'dispatch' => [
|
'dispatch' => [
|
||||||
'middleware' => [
|
'middleware' => [
|
||||||
Mezzio\Router\Middleware\DispatchMiddleware::class,
|
Router\Middleware\DispatchMiddleware::class,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -67,4 +69,5 @@ return [
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
@ -4,7 +4,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Shlinkio\Shlink\Core\Action;
|
namespace Shlinkio\Shlink\Core\Action;
|
||||||
|
|
||||||
|
use Fig\Http\Message\RequestMethodInterface;
|
||||||
use Laminas\Diactoros\Uri;
|
use Laminas\Diactoros\Uri;
|
||||||
|
use Mezzio\Router\Middleware\ImplicitHeadMiddleware;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
@ -24,7 +26,7 @@ use function array_merge;
|
|||||||
use function GuzzleHttp\Psr7\build_query;
|
use function GuzzleHttp\Psr7\build_query;
|
||||||
use function GuzzleHttp\Psr7\parse_query;
|
use function GuzzleHttp\Psr7\parse_query;
|
||||||
|
|
||||||
abstract class AbstractTrackingAction implements MiddlewareInterface
|
abstract class AbstractTrackingAction implements MiddlewareInterface, RequestMethodInterface
|
||||||
{
|
{
|
||||||
private ShortUrlResolverInterface $urlResolver;
|
private ShortUrlResolverInterface $urlResolver;
|
||||||
private VisitsTrackerInterface $visitTracker;
|
private VisitsTrackerInterface $visitTracker;
|
||||||
@ -50,14 +52,13 @@ abstract class AbstractTrackingAction implements MiddlewareInterface
|
|||||||
$disableTrackParam = $this->appOptions->getDisableTrackParam();
|
$disableTrackParam = $this->appOptions->getDisableTrackParam();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$url = $this->urlResolver->resolveEnabledShortUrl($identifier);
|
$shortUrl = $this->urlResolver->resolveEnabledShortUrl($identifier);
|
||||||
|
|
||||||
// Track visit to this short code
|
if ($this->shouldTrackRequest($request, $query, $disableTrackParam)) {
|
||||||
if ($disableTrackParam === null || ! array_key_exists($disableTrackParam, $query)) {
|
$this->visitTracker->track($shortUrl, Visitor::fromRequest($request));
|
||||||
$this->visitTracker->track($url, Visitor::fromRequest($request));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->createSuccessResp($this->buildUrlToRedirectTo($url, $query, $disableTrackParam));
|
return $this->createSuccessResp($this->buildUrlToRedirectTo($shortUrl, $query, $disableTrackParam));
|
||||||
} catch (ShortUrlNotFoundException $e) {
|
} catch (ShortUrlNotFoundException $e) {
|
||||||
$this->logger->warning('An error occurred while tracking short code. {e}', ['e' => $e]);
|
$this->logger->warning('An error occurred while tracking short code. {e}', ['e' => $e]);
|
||||||
return $this->createErrorResp($request, $handler);
|
return $this->createErrorResp($request, $handler);
|
||||||
@ -76,6 +77,16 @@ abstract class AbstractTrackingAction implements MiddlewareInterface
|
|||||||
return (string) $uri->withQuery(build_query($mergedQuery));
|
return (string) $uri->withQuery(build_query($mergedQuery));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function shouldTrackRequest(ServerRequestInterface $request, array $query, ?string $disableTrackParam): bool
|
||||||
|
{
|
||||||
|
$forwardedMethod = $request->getAttribute(ImplicitHeadMiddleware::FORWARDED_HTTP_METHOD_ATTRIBUTE);
|
||||||
|
if ($forwardedMethod === self::METHOD_HEAD) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $disableTrackParam === null || ! array_key_exists($disableTrackParam, $query);
|
||||||
|
}
|
||||||
|
|
||||||
abstract protected function createSuccessResp(string $longUrl): ResponseInterface;
|
abstract protected function createSuccessResp(string $longUrl): ResponseInterface;
|
||||||
|
|
||||||
abstract protected function createErrorResp(
|
abstract protected function createErrorResp(
|
||||||
|
@ -4,8 +4,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace ShlinkioTest\Shlink\Core\Action;
|
namespace ShlinkioTest\Shlink\Core\Action;
|
||||||
|
|
||||||
|
use Fig\Http\Message\RequestMethodInterface;
|
||||||
use Laminas\Diactoros\Response;
|
use Laminas\Diactoros\Response;
|
||||||
use Laminas\Diactoros\ServerRequest;
|
use Laminas\Diactoros\ServerRequest;
|
||||||
|
use Mezzio\Router\Middleware\ImplicitHeadMiddleware;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Prophecy\Argument;
|
use Prophecy\Argument;
|
||||||
use Prophecy\Prophecy\ObjectProphecy;
|
use Prophecy\Prophecy\ObjectProphecy;
|
||||||
@ -89,4 +91,23 @@ class RedirectActionTest extends TestCase
|
|||||||
|
|
||||||
$handle->shouldHaveBeenCalledOnce();
|
$handle->shouldHaveBeenCalledOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function trackingIsDisabledWhenRequestIsForwardedFromHead(): void
|
||||||
|
{
|
||||||
|
$shortCode = 'abc123';
|
||||||
|
$shortUrl = new ShortUrl('http://domain.com/foo/bar?some=thing');
|
||||||
|
$this->urlResolver->resolveEnabledShortUrl(new ShortUrlIdentifier($shortCode, ''))->willReturn($shortUrl);
|
||||||
|
$track = $this->visitTracker->track(Argument::cetera())->will(function (): void {
|
||||||
|
});
|
||||||
|
|
||||||
|
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode)
|
||||||
|
->withAttribute(
|
||||||
|
ImplicitHeadMiddleware::FORWARDED_HTTP_METHOD_ATTRIBUTE,
|
||||||
|
RequestMethodInterface::METHOD_HEAD,
|
||||||
|
);
|
||||||
|
$this->action->process($request, $this->prophesize(RequestHandlerInterface::class)->reveal());
|
||||||
|
|
||||||
|
$track->shouldNotHaveBeenCalled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user