From 9bfd3fef1aff2992d61f70285c12c82365a011f9 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Wed, 23 Aug 2023 01:02:56 +0600 Subject: [PATCH] Add Swagger API documentation and proxy routing. Added Swagger as a new service in the docker-compose file for generating the API documentation. The new API documentation is provided via an OpenAPI file located at `public/swagger.json`. Changes in routing were done to handle /api-docs requests and redirect them to the running Swagger UI instance. This will make API easier to understand and debug. --- docker-compose.yml | 9 ++ docker/dev/angie/config/default.conf | 12 +- public/swagger.json | 226 +++++++++++++++++++++++++++ 3 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 public/swagger.json diff --git a/docker-compose.yml b/docker-compose.yml index eff1f1f..d1e1558 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,6 +40,15 @@ services: volumes: - ./docker/dev/db:/var/lib/mysql - ./docker/dev/my.cnf:/etc/mysql/conf.d/my.cnf + swagger: + image: swaggerapi/swagger-ui + environment: + URLS: "[ { url: '/swagger.json', name: '/swagger.json' } ]" + BASE_URL: /api-docs + ports: + - "8080" +# volumes: +# - ./docker/swagger:/swagger adminer: image: adminer #restart: always diff --git a/docker/dev/angie/config/default.conf b/docker/dev/angie/config/default.conf index c2de888..3063a8a 100644 --- a/docker/dev/angie/config/default.conf +++ b/docker/dev/angie/config/default.conf @@ -8,8 +8,16 @@ server { root /var/www/html/public; location / { - # try to serve file directly, fallback to index.php - try_files $uri /index.php$is_args$args; + location /api-docs { + proxy_pass http://swagger:8080; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + } + location / { + # try to serve file directly, fallback to index.php + try_files $uri /index.php$is_args$args; + } } location ~ ^/index\.php(/|$) { diff --git a/public/swagger.json b/public/swagger.json new file mode 100644 index 0000000..29a45f2 --- /dev/null +++ b/public/swagger.json @@ -0,0 +1,226 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Captcha service - API", + "description": "API Documentation.", + "version": "1.0.0" + }, + "servers": [ + { + "url": "/api/v1" + } + ], + "tags": [ + { + "name": "captcha", + "description": "Operations about captcha" + } + ], + "paths": { + "/captcha": { + "get": { + "tags": [ + "captcha" + ], + "summary": "Captcha generation", + "description": "", + "operationId": "captchaGeneration", + "parameters": [ + { + "name": "public_token", + "in": "header", + "description": "Public token for captcha generation", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Captcha" + } + } + } + } + }, + "403": { + "description": "Invalid public token value" + } + } + }, + "post": { + "tags": [ + "captcha" + ], + "summary": "Checking captcha", + "description": "", + "operationId": "captchaChecking", + "parameters": [ + { + "name": "public_token", + "in": "header", + "description": "Public token for captcha generation", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CaptchaChecking" + } + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CaptchaVerification" + } + } + } + } + }, + "403": { + "description": "Invalid public token value" + } + } + } + }, + "/captcha/{captcha_key}": { + "get": { + "tags": [ + "captcha" + ], + "summary": "Verification Information", + "description": "", + "operationId": "CaptchaKeyInfo", + "parameters": [ + { + "name": "private_token", + "in": "header", + "description": "Private token for captcha verification", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "captcha_key", + "in": "path", + "description": "The key that we received when generating the captcha", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CaptchaKeyInfo" + } + } + } + } + }, + "403": { + "description": "Invalid private token value" + }, + "404": { + "description": "Captcha key not found" + } + } + } + } + }, + "components": { + "schemas": { + "Captcha": { + "type": "object", + "properties": { + "image_base64": { + "type": "string", + "format": "byte" + }, + "image_text_base64": { + "type": "string", + "format": "byte" + }, + "captcha_key": { + "type": "string" + } + }, + "required": [ + "image_base64", "image_text_base64", "captcha_key" + ] + }, + "CaptchaVerification": { + "type": "object", + "properties": { + "status": { + "type": "boolean" + }, + "message": { + "type": "string" + } + }, + "required": [ + "status", "message" + ] + }, + "CaptchaChecking": { + "type": "object", + "properties": { + "captcha_key": { + "type": "string" + }, + "verification": { + "type": "array", + "example": [{"x": 10, "y": 20}, {"x": 30, "y": 30}, {"x": 60, "y": 50}] + } + }, + "required": [ + "captcha_key", "verification" + ] + }, + "CaptchaKeyInfo": { + "type": "object", + "properties": { + "status": { + "type": "boolean" + }, + "message": { + "type": "string" + } + }, + "required": [ + "status", "message" + ] + } + } + } +}