Skip to content

Commit

Permalink
fixes and tests router
Browse files Browse the repository at this point in the history
  • Loading branch information
charjr committed Feb 17, 2023
1 parent a2f3eba commit cfd3683
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 185 deletions.
49 changes: 45 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,54 @@ and [Nicolas Grekas](https://nicolas-grekas.medium.com/making-symfonys-router-77

## Routing Priorities

- [Static urls MUST be prioritized over dynamic urls](https://spec.openapis.org/oas/v3.1.0#paths-object)
- Longer urls are prioritized over shorter urls
- Hosted servers will be prioritized over hostless servers
- [Static urls MUST be prioritized over dynamic urls](https://spec.openapis.org/oas/v3.1.0#paths-object).
- Longer urls are prioritized over shorter urls.
- Hosted servers will be prioritized over hostless servers.

# Installation

```text
composer require membrane/openapi-router
```

# Quick Start

Run the following console command to cache the routes from your OpenAPI
To read routes dynamically, you can do the following:

```php
<?php

use Membrane\OpenAPIRouter\Reader\OpenAPIFileReader;
use Membrane\OpenAPIRouter\Router\Collector\RouteCollector;
use Membrane\OpenAPIRouter\Router\Router;

$openApi = (new OpenAPIFileReader())->readFromAbsoluteFilePath('/app/petstore.yaml');
$routeCollection = (new RouteCollector())->collect($openApi);

$router = new Router($routeCollection);
$requestedOperationId = $router->route('http://petstore.swagger.io/v1/pets', 'get');

echo $requestedOperationId; // listPets
```

# Caching Routes

Run the following console command to cache the routes from your OpenAPI, to avoid reading your OpenAPI file everytime:

```text
membrane:router:generate-routes <openapi-filepath> <destination-filepath>
```


```php
<?php

use Membrane\OpenAPIRouter\Router\Router;

$routeCollection = include '/app/cache/routes.php';

$router = new Router($routeCollection);
$requestedOperationId = $router->route('http://petstore.swagger.io/v1/pets', 'get');

echo $requestedOperationId; // listPets
```
13 changes: 13 additions & 0 deletions bin/membrane-router
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env php
<?php

require __DIR__ . '/../vendor/autoload.php';

use Membrane\OpenAPIRouter\Console\Commands\CacheOpenAPI;
use Symfony\Component\Console\Application;

$application = new Application();

$application->add(new CacheOpenAPI());

$application->run();
41 changes: 27 additions & 14 deletions src/Console/Commands/CacheOpenAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Membrane\OpenAPIRouter\Router\ValueObject\RouteCollection;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -22,7 +23,7 @@
)]
class CacheOpenAPI extends Command
{
protected function configure()
protected function configure(): void
{
self::addArgument(
'openAPI',
Expand All @@ -32,44 +33,56 @@ protected function configure()
self::addArgument(
'destination',
InputArgument::OPTIONAL,
'The absolute filepath for the generated route collection',
'The filepath for the generated route collection',
__DIR__ . '/../../../cache/routes.php'
);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$openAPIFilePath = $input->getArgument('openAPI');
$destination = $input->getArgument('destination');
assert(is_string($openAPIFilePath));
$existingFilePath = $destination = $input->getArgument('destination');
assert(is_string($existingFilePath) && is_string($destination));

while (!file_exists($existingFilePath)) {
$existingFilePath = dirname($existingFilePath);
}
if (!is_writable($existingFilePath)) {
$this->outputErrorBlock(sprintf('%s cannot be written to', $existingFilePath), $output);
return Command::FAILURE;
}

try {
assert(is_string($openAPIFilePath));
$openApi = (new OpenAPIFileReader())->readFromAbsoluteFilePath($openAPIFilePath);
} catch (CannotReadOpenAPI $e) {
$output->writeln($e->getMessage());
return Command::INVALID;
}

assert(is_string($destination));
if (is_writable($destination)) {
echo sprintf('%s is an invalid filename', $destination);
return Command::INVALID;
$this->outputErrorBlock($e->getMessage(), $output);
return Command::FAILURE;
}

try {
$routeCollection = (new RouteCollector())->collect($openApi);
} catch (CannotRouteOpenAPI | CannotProcessOpenAPI $e) {
$output->writeln($e->getMessage());
return Command::INVALID;
$this->outputErrorBlock($e->getMessage(), $output);
return Command::FAILURE;
}

$routes = sprintf(
'<?php return new %s(%s);',
RouteCollection::class,
var_export($routeCollection->routes, true)
);


mkdir(dirname($destination), recursive: true);
file_put_contents($destination, $routes);

return Command::SUCCESS;
}

private function outputErrorBlock(string $message, OutputInterface $output): void
{
$formattedMessage = (new FormatterHelper())->formatBlock($message, 'error', true);
$output->writeLn(sprintf("\n%s\n", $formattedMessage));
}
}
6 changes: 3 additions & 3 deletions src/Reader/OpenAPIFileReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ class OpenAPIFileReader
public function __construct()
{
$this->supportedFileTypes = [
'json' => fn($p) => Reader::readFromJsonFile(fileName: $p, resolveReferences: false),
'yaml' => fn($p) => Reader::readFromYamlFile(fileName: $p, resolveReferences: false),
'yml' => fn($p) => Reader::readFromYamlFile(fileName: $p, resolveReferences: false),
'json' => fn($p) => Reader::readFromJsonFile(fileName: $p),
'yaml' => fn($p) => Reader::readFromYamlFile(fileName: $p),
'yml' => fn($p) => Reader::readFromYamlFile(fileName: $p),
];
}

Expand Down
Loading

0 comments on commit cfd3683

Please sign in to comment.