Added support for domain param to command and action to resolve a short URL

This commit is contained in:
Alejandro Celaya 2019-10-04 21:17:02 +02:00
parent 8d3a49a319
commit baf3093893
7 changed files with 47 additions and 23 deletions

View file

@ -16,4 +16,11 @@ return [
], ],
], ],
'host_resolution' => [
'headers_to_inspect' => [
'Host',
'X-Forwarded-Host',
],
],
]; ];

View file

@ -216,6 +216,10 @@
"findIfExists": { "findIfExists": {
"description": "Will force existing matching URL to be returned if found, instead of creating a new one", "description": "Will force existing matching URL to be returned if found, instead of creating a new one",
"type": "boolean" "type": "boolean"
},
"domain": {
"description": "The domain to which the short URL will be attached",
"type": "string"
} }
} }
} }

View file

@ -15,6 +15,15 @@
"schema": { "schema": {
"type": "string" "type": "string"
} }
},
{
"name": "domain",
"in": "query",
"description": "The domain in which the short code should be searched for. Will fall back to default domain if not found.",
"required": false,
"schema": {
"type": "string"
}
} }
], ],
"security": [ "security": [

View file

@ -10,6 +10,7 @@ use Shlinkio\Shlink\Core\Service\UrlShortenerInterface;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
@ -35,7 +36,8 @@ class ResolveUrlCommand extends Command
->setName(self::NAME) ->setName(self::NAME)
->setAliases(self::ALIASES) ->setAliases(self::ALIASES)
->setDescription('Returns the long URL behind a short code') ->setDescription('Returns the long URL behind a short code')
->addArgument('shortCode', InputArgument::REQUIRED, 'The short code to parse'); ->addArgument('shortCode', InputArgument::REQUIRED, 'The short code to parse')
->addOption('domain', 'd', InputOption::VALUE_REQUIRED, 'The domain to which the short URL is attached.');
} }
protected function interact(InputInterface $input, OutputInterface $output): void protected function interact(InputInterface $input, OutputInterface $output): void
@ -56,9 +58,10 @@ class ResolveUrlCommand extends Command
{ {
$io = new SymfonyStyle($input, $output); $io = new SymfonyStyle($input, $output);
$shortCode = $input->getArgument('shortCode'); $shortCode = $input->getArgument('shortCode');
$domain = $input->getOption('domain');
try { try {
$url = $this->urlShortener->shortCodeToUrl($shortCode); $url = $this->urlShortener->shortCodeToUrl($shortCode, $domain);
$output->writeln(sprintf('Long URL: <info>%s</info>', $url->getLongUrl())); $output->writeln(sprintf('Long URL: <info>%s</info>', $url->getLongUrl()));
return ExitCodes::EXIT_SUCCESS; return ExitCodes::EXIT_SUCCESS;
} catch (InvalidShortCodeException $e) { } catch (InvalidShortCodeException $e) {

View file

@ -33,13 +33,13 @@ class ResolveUrlCommandTest extends TestCase
} }
/** @test */ /** @test */
public function correctShortCodeResolvesUrl() public function correctShortCodeResolvesUrl(): void
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$expectedUrl = 'http://domain.com/foo/bar'; $expectedUrl = 'http://domain.com/foo/bar';
$shortUrl = new ShortUrl($expectedUrl); $shortUrl = new ShortUrl($expectedUrl);
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn($shortUrl) $this->urlShortener->shortCodeToUrl($shortCode, null)->willReturn($shortUrl)
->shouldBeCalledOnce(); ->shouldBeCalledOnce();
$this->commandTester->execute(['shortCode' => $shortCode]); $this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay(); $output = $this->commandTester->getDisplay();
@ -47,11 +47,11 @@ class ResolveUrlCommandTest extends TestCase
} }
/** @test */ /** @test */
public function incorrectShortCodeOutputsErrorMessage() public function incorrectShortCodeOutputsErrorMessage(): void
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(EntityDoesNotExistException::class) $this->urlShortener->shortCodeToUrl($shortCode, null)->willThrow(EntityDoesNotExistException::class)
->shouldBeCalledOnce(); ->shouldBeCalledOnce();
$this->commandTester->execute(['shortCode' => $shortCode]); $this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay(); $output = $this->commandTester->getDisplay();
@ -59,11 +59,11 @@ class ResolveUrlCommandTest extends TestCase
} }
/** @test */ /** @test */
public function wrongShortCodeFormatOutputsErrorMessage() public function wrongShortCodeFormatOutputsErrorMessage(): void
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(new InvalidShortCodeException()) $this->urlShortener->shortCodeToUrl($shortCode, null)->willThrow(new InvalidShortCodeException())
->shouldBeCalledOnce(); ->shouldBeCalledOnce();
$this->commandTester->execute(['shortCode' => $shortCode]); $this->commandTester->execute(['shortCode' => $shortCode]);
$output = $this->commandTester->getDisplay(); $output = $this->commandTester->getDisplay();

View file

@ -45,10 +45,11 @@ class ResolveShortUrlAction extends AbstractRestAction
public function handle(Request $request): Response public function handle(Request $request): Response
{ {
$shortCode = $request->getAttribute('shortCode'); $shortCode = $request->getAttribute('shortCode');
$domain = $request->getQueryParams()['domain'] ?? null;
$transformer = new ShortUrlDataTransformer($this->domainConfig); $transformer = new ShortUrlDataTransformer($this->domainConfig);
try { try {
$url = $this->urlShortener->shortCodeToUrl($shortCode); $url = $this->urlShortener->shortCodeToUrl($shortCode, $domain);
return new JsonResponse($transformer->transform($url)); return new JsonResponse($transformer->transform($url));
} catch (InvalidShortCodeException $e) { } catch (InvalidShortCodeException $e) {
$this->logger->warning('Provided short code with invalid format. {e}', ['e' => $e]); $this->logger->warning('Provided short code with invalid format. {e}', ['e' => $e]);

View file

@ -30,11 +30,11 @@ class ResolveShortUrlActionTest extends TestCase
} }
/** @test */ /** @test */
public function incorrectShortCodeReturnsError() public function incorrectShortCodeReturnsError(): void
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(EntityDoesNotExistException::class) $this->urlShortener->shortCodeToUrl($shortCode, null)->willThrow(EntityDoesNotExistException::class)
->shouldBeCalledOnce(); ->shouldBeCalledOnce();
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode); $request = (new ServerRequest())->withAttribute('shortCode', $shortCode);
$response = $this->action->handle($request); $response = $this->action->handle($request);
@ -43,10 +43,10 @@ class ResolveShortUrlActionTest extends TestCase
} }
/** @test */ /** @test */
public function correctShortCodeReturnsSuccess() public function correctShortCodeReturnsSuccess(): void
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willReturn( $this->urlShortener->shortCodeToUrl($shortCode, null)->willReturn(
new ShortUrl('http://domain.com/foo/bar') new ShortUrl('http://domain.com/foo/bar')
)->shouldBeCalledOnce(); )->shouldBeCalledOnce();
@ -57,11 +57,11 @@ class ResolveShortUrlActionTest extends TestCase
} }
/** @test */ /** @test */
public function invalidShortCodeExceptionReturnsError() public function invalidShortCodeExceptionReturnsError(): void
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(InvalidShortCodeException::class) $this->urlShortener->shortCodeToUrl($shortCode, null)->willThrow(InvalidShortCodeException::class)
->shouldBeCalledOnce(); ->shouldBeCalledOnce();
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode); $request = (new ServerRequest())->withAttribute('shortCode', $shortCode);
$response = $this->action->handle($request); $response = $this->action->handle($request);
@ -70,11 +70,11 @@ class ResolveShortUrlActionTest extends TestCase
} }
/** @test */ /** @test */
public function unexpectedExceptionWillReturnError() public function unexpectedExceptionWillReturnError(): void
{ {
$shortCode = 'abc123'; $shortCode = 'abc123';
$this->urlShortener->shortCodeToUrl($shortCode)->willThrow(Exception::class) $this->urlShortener->shortCodeToUrl($shortCode, null)->willThrow(Exception::class)
->shouldBeCalledOnce(); ->shouldBeCalledOnce();
$request = (new ServerRequest())->withAttribute('shortCode', $shortCode); $request = (new ServerRequest())->withAttribute('shortCode', $shortCode);
$response = $this->action->handle($request); $response = $this->action->handle($request);