Search code examples
flaskaws-lambdaswaggerserverless

AWS Lambda adds $default to the path of flasgger apispec


AWS Lambda request url is: https://<id>.<region>.amazonaws.com/$default/apispec.json

Screenshot

The URL should be https://<id>.<region>.amazonaws.com/apispec.json

It's fine when I manually remove the $default though.

This is bugging us, so if anyone could help us, it will be much appreciated.

Swagger Config:

swagger_config['swagger_ui_bundle_js'] = '//unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js'
swagger_config['swagger_ui_standalone_preset_js'] = '//unpkg.com/swagger-ui-dist@3/swagger-ui-standalone-preset.js'
swagger_config['jquery_js'] = '//unpkg.com/jquery@2.2.4/dist/jquery.min.js'
swagger_config['swagger_ui_css'] = '//unpkg.com/swagger-ui-dist@3/swagger-ui.css'
# swagger_config['specs'][0] = {'endpoint':'/cms-api/apispec','route':'/cms-api/apispec.json'}
Swagger(app, config=swagger_config, template=template)

swagger_config

swagger_config = {
    "headers": [
        
    ],
    "specs": [
        {
            "endpoint": 'apispec',
            "route": '/apispec.json',
            "rule_filter": lambda rule: True,  # all in
            "model_filter": lambda tag: True,  # all in
        }
    ],
    "static_url_path": "/flasgger_static",
    "swagger_ui": True,
    "specs_route": "/cms-api"
}

serverless.yml

service: cms-backend

frameworkVersion: '3'

custom:
  wsgi:
    app: src.__init__.app

provider:
  name: aws
  stage: ${opt:stage, 'dev'}
  runtime: python3.8
  logs:
    httpApi: true
  httpApi:
    metrics: true
    cors: true
  region: ap-southeast-1

functions:
  app:
    handler: wsgi_handler.handler
    events:
      - httpApi: '*'

plugins:
  - serverless-wsgi
  - serverless-python-requirements

Solution

  • Encountered a similar issue and it took me longer than I wanted to figure it out, but it turned out to be related to the API gateway stages. Serverless doesn't use this feature and just deploys a new function for a different stage.

    If you're not using the stages of the API Gateway, try leaving them out by adding the STRIP_STAGE_PATH environment variable as mentioned in the serverless-wsgi documentation. It should leave out the $default stage variable from your path:

    provider:
      environment:
        STRIP_STAGE_PATH: yes
    

    (This is a code snippet of the source code of the serverless_wsgi module):

    def get_script_name(headers, request_context):
        strip_stage_path = os.environ.get("STRIP_STAGE_PATH", "").lower().strip() in
            [
            "yes",
            "y",
            "true",
            "t",
            "1",
        ]
    
        if "amazonaws.com" in headers.get("Host", "") and not strip_stage_path:
            script_name = "/{}".format(request_context.get("stage", ""))
        else:
            script_name = ""
        return script_name