'POST', 'basePathWithoutHost' => '/v2', 'path' => '/pet', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractPetApi', 'userClassname' => 'PetApi', 'operationId' => 'addPet', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/xml" : { "schema" : { "$ref" : "#/components/schemas/Pet" } }, "application/json" : { "schema" : { "$ref" : "#/components/schemas/Pet" } } } }', ], '405' => [ 'jsonSchema' => '{ "description" : "Invalid input" }', ], ], 'authMethods' => [ // oauth2 security schema named 'petstore_auth' [ 'type' => 'oauth2', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => false, 'isOAuth' => true, 'scopes' => [ 'write:pets', // modify pets in your account 'read:pets', // read your pets ], ], ], ], [ 'httpMethod' => 'GET', 'basePathWithoutHost' => '/v2', 'path' => '/pet/findByStatus', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractPetApi', 'userClassname' => 'PetApi', 'operationId' => 'findPetsByStatus', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/xml" : { "schema" : { "type" : "array", "items" : { "$ref" : "#/components/schemas/Pet" } } }, "application/json" : { "schema" : { "type" : "array", "items" : { "$ref" : "#/components/schemas/Pet" } } } } }', ], '400' => [ 'jsonSchema' => '{ "description" : "Invalid status value" }', ], ], 'authMethods' => [ // oauth2 security schema named 'petstore_auth' [ 'type' => 'oauth2', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => false, 'isOAuth' => true, 'scopes' => [ 'read:pets', // read your pets ], ], ], ], [ 'httpMethod' => 'GET', 'basePathWithoutHost' => '/v2', 'path' => '/pet/findByTags', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractPetApi', 'userClassname' => 'PetApi', 'operationId' => 'findPetsByTags', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/xml" : { "schema" : { "type" : "array", "items" : { "$ref" : "#/components/schemas/Pet" } } }, "application/json" : { "schema" : { "type" : "array", "items" : { "$ref" : "#/components/schemas/Pet" } } } } }', ], '400' => [ 'jsonSchema' => '{ "description" : "Invalid tag value" }', ], ], 'authMethods' => [ // oauth2 security schema named 'petstore_auth' [ 'type' => 'oauth2', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => false, 'isOAuth' => true, 'scopes' => [ 'read:pets', // read your pets ], ], ], ], [ 'httpMethod' => 'PUT', 'basePathWithoutHost' => '/v2', 'path' => '/pet', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractPetApi', 'userClassname' => 'PetApi', 'operationId' => 'updatePet', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/xml" : { "schema" : { "$ref" : "#/components/schemas/Pet" } }, "application/json" : { "schema" : { "$ref" : "#/components/schemas/Pet" } } } }', ], '400' => [ 'jsonSchema' => '{ "description" : "Invalid ID supplied" }', ], '404' => [ 'jsonSchema' => '{ "description" : "Pet not found" }', ], '405' => [ 'jsonSchema' => '{ "description" : "Validation exception" }', ], ], 'authMethods' => [ // oauth2 security schema named 'petstore_auth' [ 'type' => 'oauth2', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => false, 'isOAuth' => true, 'scopes' => [ 'write:pets', // modify pets in your account 'read:pets', // read your pets ], ], ], ], [ 'httpMethod' => 'DELETE', 'basePathWithoutHost' => '/v2', 'path' => '/pet/{petId}', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractPetApi', 'userClassname' => 'PetApi', 'operationId' => 'deletePet', 'responses' => [ '400' => [ 'jsonSchema' => '{ "description" : "Invalid pet value" }', ], ], 'authMethods' => [ // oauth2 security schema named 'petstore_auth' [ 'type' => 'oauth2', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => false, 'isOAuth' => true, 'scopes' => [ 'write:pets', // modify pets in your account 'read:pets', // read your pets ], ], ], ], [ 'httpMethod' => 'GET', 'basePathWithoutHost' => '/v2', 'path' => '/pet/{petId}', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractPetApi', 'userClassname' => 'PetApi', 'operationId' => 'getPetById', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/xml" : { "schema" : { "$ref" : "#/components/schemas/Pet" } }, "application/json" : { "schema" : { "$ref" : "#/components/schemas/Pet" } } } }', ], '400' => [ 'jsonSchema' => '{ "description" : "Invalid ID supplied" }', ], '404' => [ 'jsonSchema' => '{ "description" : "Pet not found" }', ], ], 'authMethods' => [ // apiKey security schema named 'api_key' [ 'type' => 'apiKey', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => true, 'isOAuth' => false, 'keyParamName' => 'api_key', 'isKeyInHeader' => true, 'isKeyInQuery' => false, 'isKeyInCookie' => false, ], ], ], [ 'httpMethod' => 'POST', 'basePathWithoutHost' => '/v2', 'path' => '/pet/{petId}', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractPetApi', 'userClassname' => 'PetApi', 'operationId' => 'updatePetWithForm', 'responses' => [ '405' => [ 'jsonSchema' => '{ "description" : "Invalid input" }', ], ], 'authMethods' => [ // oauth2 security schema named 'petstore_auth' [ 'type' => 'oauth2', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => false, 'isOAuth' => true, 'scopes' => [ 'write:pets', // modify pets in your account 'read:pets', // read your pets ], ], ], ], [ 'httpMethod' => 'POST', 'basePathWithoutHost' => '/v2', 'path' => '/pet/{petId}/uploadImage', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractPetApi', 'userClassname' => 'PetApi', 'operationId' => 'uploadFile', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/json" : { "schema" : { "$ref" : "#/components/schemas/ApiResponse" } } } }', ], ], 'authMethods' => [ // oauth2 security schema named 'petstore_auth' [ 'type' => 'oauth2', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => false, 'isOAuth' => true, 'scopes' => [ 'write:pets', // modify pets in your account 'read:pets', // read your pets ], ], ], ], [ 'httpMethod' => 'GET', 'basePathWithoutHost' => '/v2', 'path' => '/store/inventory', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractStoreApi', 'userClassname' => 'StoreApi', 'operationId' => 'getInventory', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/json" : { "schema" : { "type" : "object", "additionalProperties" : { "type" : "integer", "format" : "int32" } } } } }', ], ], 'authMethods' => [ // apiKey security schema named 'api_key' [ 'type' => 'apiKey', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => true, 'isOAuth' => false, 'keyParamName' => 'api_key', 'isKeyInHeader' => true, 'isKeyInQuery' => false, 'isKeyInCookie' => false, ], ], ], [ 'httpMethod' => 'POST', 'basePathWithoutHost' => '/v2', 'path' => '/store/order', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractStoreApi', 'userClassname' => 'StoreApi', 'operationId' => 'placeOrder', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/xml" : { "schema" : { "$ref" : "#/components/schemas/Order" } }, "application/json" : { "schema" : { "$ref" : "#/components/schemas/Order" } } } }', ], '400' => [ 'jsonSchema' => '{ "description" : "Invalid Order" }', ], ], 'authMethods' => [ ], ], [ 'httpMethod' => 'DELETE', 'basePathWithoutHost' => '/v2', 'path' => '/store/order/{orderId}', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractStoreApi', 'userClassname' => 'StoreApi', 'operationId' => 'deleteOrder', 'responses' => [ '400' => [ 'jsonSchema' => '{ "description" : "Invalid ID supplied" }', ], '404' => [ 'jsonSchema' => '{ "description" : "Order not found" }', ], ], 'authMethods' => [ ], ], [ 'httpMethod' => 'GET', 'basePathWithoutHost' => '/v2', 'path' => '/store/order/{orderId}', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractStoreApi', 'userClassname' => 'StoreApi', 'operationId' => 'getOrderById', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/xml" : { "schema" : { "$ref" : "#/components/schemas/Order" } }, "application/json" : { "schema" : { "$ref" : "#/components/schemas/Order" } } } }', ], '400' => [ 'jsonSchema' => '{ "description" : "Invalid ID supplied" }', ], '404' => [ 'jsonSchema' => '{ "description" : "Order not found" }', ], ], 'authMethods' => [ ], ], [ 'httpMethod' => 'POST', 'basePathWithoutHost' => '/v2', 'path' => '/user', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractUserApi', 'userClassname' => 'UserApi', 'operationId' => 'createUser', 'responses' => [ 'default' => [ 'jsonSchema' => '{ "description" : "successful operation" }', ], ], 'authMethods' => [ // apiKey security schema named 'api_key' [ 'type' => 'apiKey', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => true, 'isOAuth' => false, 'keyParamName' => 'api_key', 'isKeyInHeader' => true, 'isKeyInQuery' => false, 'isKeyInCookie' => false, ], ], ], [ 'httpMethod' => 'POST', 'basePathWithoutHost' => '/v2', 'path' => '/user/createWithArray', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractUserApi', 'userClassname' => 'UserApi', 'operationId' => 'createUsersWithArrayInput', 'responses' => [ 'default' => [ 'jsonSchema' => '{ "description" : "successful operation" }', ], ], 'authMethods' => [ // apiKey security schema named 'api_key' [ 'type' => 'apiKey', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => true, 'isOAuth' => false, 'keyParamName' => 'api_key', 'isKeyInHeader' => true, 'isKeyInQuery' => false, 'isKeyInCookie' => false, ], ], ], [ 'httpMethod' => 'POST', 'basePathWithoutHost' => '/v2', 'path' => '/user/createWithList', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractUserApi', 'userClassname' => 'UserApi', 'operationId' => 'createUsersWithListInput', 'responses' => [ 'default' => [ 'jsonSchema' => '{ "description" : "successful operation" }', ], ], 'authMethods' => [ // apiKey security schema named 'api_key' [ 'type' => 'apiKey', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => true, 'isOAuth' => false, 'keyParamName' => 'api_key', 'isKeyInHeader' => true, 'isKeyInQuery' => false, 'isKeyInCookie' => false, ], ], ], [ 'httpMethod' => 'GET', 'basePathWithoutHost' => '/v2', 'path' => '/user/login', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractUserApi', 'userClassname' => 'UserApi', 'operationId' => 'loginUser', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "headers" : { "Set-Cookie" : { "description" : "Cookie authentication key for use with the `api_key` apiKey authentication.", "style" : "simple", "explode" : false, "schema" : { "type" : "string", "example" : "AUTH_KEY=abcde12345; Path=/; HttpOnly" } }, "X-Rate-Limit" : { "description" : "calls per hour allowed by the user", "style" : "simple", "explode" : false, "schema" : { "type" : "integer", "format" : "int32" } }, "X-Expires-After" : { "description" : "date in UTC when token expires", "style" : "simple", "explode" : false, "schema" : { "type" : "string", "format" : "date-time" } } }, "content" : { "application/xml" : { "schema" : { "type" : "string" } }, "application/json" : { "schema" : { "type" : "string" } } } }', ], '400' => [ 'jsonSchema' => '{ "description" : "Invalid username/password supplied" }', ], ], 'authMethods' => [ ], ], [ 'httpMethod' => 'GET', 'basePathWithoutHost' => '/v2', 'path' => '/user/logout', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractUserApi', 'userClassname' => 'UserApi', 'operationId' => 'logoutUser', 'responses' => [ 'default' => [ 'jsonSchema' => '{ "description" : "successful operation" }', ], ], 'authMethods' => [ // apiKey security schema named 'api_key' [ 'type' => 'apiKey', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => true, 'isOAuth' => false, 'keyParamName' => 'api_key', 'isKeyInHeader' => true, 'isKeyInQuery' => false, 'isKeyInCookie' => false, ], ], ], [ 'httpMethod' => 'DELETE', 'basePathWithoutHost' => '/v2', 'path' => '/user/{username}', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractUserApi', 'userClassname' => 'UserApi', 'operationId' => 'deleteUser', 'responses' => [ '400' => [ 'jsonSchema' => '{ "description" : "Invalid username supplied" }', ], '404' => [ 'jsonSchema' => '{ "description" : "User not found" }', ], ], 'authMethods' => [ // apiKey security schema named 'api_key' [ 'type' => 'apiKey', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => true, 'isOAuth' => false, 'keyParamName' => 'api_key', 'isKeyInHeader' => true, 'isKeyInQuery' => false, 'isKeyInCookie' => false, ], ], ], [ 'httpMethod' => 'GET', 'basePathWithoutHost' => '/v2', 'path' => '/user/{username}', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractUserApi', 'userClassname' => 'UserApi', 'operationId' => 'getUserByName', 'responses' => [ '200' => [ 'jsonSchema' => '{ "description" : "successful operation", "content" : { "application/xml" : { "schema" : { "$ref" : "#/components/schemas/User" } }, "application/json" : { "schema" : { "$ref" : "#/components/schemas/User" } } } }', ], '400' => [ 'jsonSchema' => '{ "description" : "Invalid username supplied" }', ], '404' => [ 'jsonSchema' => '{ "description" : "User not found" }', ], ], 'authMethods' => [ ], ], [ 'httpMethod' => 'PUT', 'basePathWithoutHost' => '/v2', 'path' => '/user/{username}', 'apiPackage' => 'OpenAPIServer\Api', 'classname' => 'AbstractUserApi', 'userClassname' => 'UserApi', 'operationId' => 'updateUser', 'responses' => [ '400' => [ 'jsonSchema' => '{ "description" : "Invalid user supplied" }', ], '404' => [ 'jsonSchema' => '{ "description" : "User not found" }', ], ], 'authMethods' => [ // apiKey security schema named 'api_key' [ 'type' => 'apiKey', 'isBasic' => false, 'isBearer' => false, 'isApiKey' => true, 'isOAuth' => false, 'keyParamName' => 'api_key', 'isKeyInHeader' => true, 'isKeyInQuery' => false, 'isKeyInCookie' => false, ], ], ], ]; /** * Add routes to Slim app. * * @param \Slim\App $app Pre-configured Slim application instance * * @throws HttpNotImplementedException When implementation class doesn't exists */ public function __invoke(\Slim\App $app): void { $app->options('/{routes:.*}', function (ServerRequestInterface $request, ResponseInterface $response) { // CORS Pre-Flight OPTIONS Request Handler return $response; }); // create mock middleware factory /** @var \Psr\Container\ContainerInterface */ $container = $app->getContainer(); /** @var \OpenAPIServer\Mock\OpenApiDataMockerRouteMiddlewareFactory|null */ $mockMiddlewareFactory = null; if ($container->has(\OpenAPIServer\Mock\OpenApiDataMockerRouteMiddlewareFactory::class)) { // I know, anti-pattern. Don't retrieve dependency directly from container $mockMiddlewareFactory = $container->get(\OpenAPIServer\Mock\OpenApiDataMockerRouteMiddlewareFactory::class); } foreach ($this->operations as $operation) { $callback = function (ServerRequestInterface $request) use ($operation) { $message = "How about extending {$operation['classname']} by {$operation['apiPackage']}\\{$operation['userClassname']} class implementing {$operation['operationId']} as a {$operation['httpMethod']} method?"; throw new HttpNotImplementedException($request, $message); }; $middlewares = []; if (class_exists("\\{$operation['apiPackage']}\\{$operation['userClassname']}")) { // Notice how we register the controller using the class name? // PHP-DI will instantiate the class for us only when it's actually necessary $callback = ["\\{$operation['apiPackage']}\\{$operation['userClassname']}", $operation['operationId']]; } if ($mockMiddlewareFactory) { $mockSchemaResponses = array_map(function ($item) { return json_decode($item['jsonSchema'], true); }, $operation['responses']); $middlewares[] = $mockMiddlewareFactory->create($mockSchemaResponses); } $route = $app->map( [$operation['httpMethod']], "{$operation['basePathWithoutHost']}{$operation['path']}", $callback )->setName($operation['operationId']); // Add authentication middleware based on the operation's authMethods if ($operation['authMethods']) { foreach ($operation['authMethods'] as $authMethod) { if ($authMethod['isOAuth']) { $route->add(new TokenAuthentication([ 'path' => '/', 'authenticator' => new OAuthAuthenticator($authMethod['scopes']), 'regex' => '/Bearer\s+(.*)$/i', 'header' => 'Authorization', 'parameter' => null, 'cookie' => null, 'argument' => null, 'attribute' => 'authorization_token', 'error' => ['OpenAPIServer\Auth\OAuthAuthenticator', 'handleUnauthorized'], ])); } if ($authMethod['isApiKey']) { $authenticatorConfig = [ 'path' => '/', 'authenticator' => new ApiKeyAuthenticator, 'regex' => '/\s+(.*)$/i', 'argument' => null, 'attribute' => 'authorization_token', 'error' => ['OpenAPIServer\Auth\ApiKeyAuthenticator', 'handleUnauthorized'], ]; if ($authMethod['isKeyInHeader']) { $authenticatorConfig = [ 'header' => $authMethod['keyParamName'], 'parameter' => null, 'cookie' => null, ]; } else if ($authMethod['isKeyInQuery']) { $authenticatorConfig = [ 'header' => null, 'parameter' => $authMethod['keyParamName'], 'cookie' => null, ]; } else if ($authMethod['isKeyInCookie']) { $authenticatorConfig = [ 'header' => null, 'parameter' => null, 'cookie' => $authMethod['keyParamName'], ]; } $route->add(new TokenAuthentication($authenticatorConfig)); } } } foreach ($middlewares as $middleware) { $route->add($middleware); } } } }