Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latest release (2.5.1) breaks standard swagger ui servers definition #1119

Open
code-mc opened this issue Jan 8, 2020 · 7 comments
Open
Assignees

Comments

@code-mc
Copy link

code-mc commented Jan 8, 2020

Description

The 2.5.1 release introduced changes which modify the raw openapi spec servers definition which results in a swagger ui deployment that generates invalid requests.

e.g. When you specify

servers:
  - url: /api  

And a path in your openapi spec:

paths:
  /resource/update:
    .
    .
    .
  /resource/list:
    .
    .
    .

It will generate a swagger-ui with a server "/api/resource". I suppose this is because they both share the same prefix, but this then results in the swagger ui sending requests to "/api/resource/resource/update" and "/api/resource/resource/list" instead of the expected "/api/resource/update" and "/api/resource/list".

Expected behaviour

The defined servers openapi spec property is left untouched.

Actual behaviour

The defined servers property is modified to an invalid value which breaks sending requests using swagger ui.

Steps to reproduce

See description

Additional info:

Output of the commands:

  • python --version
    Python 3.6.9

  • pip show connexion | grep "^Version\:"
    Version: 2.5.1

@dtkav dtkav self-assigned this Jan 15, 2020
@dtkav
Copy link
Collaborator

dtkav commented Jan 15, 2020

are you using flask or aiohttp?

@dtkav
Copy link
Collaborator

dtkav commented Jan 15, 2020

I was unable to reproduce the issue.
Here is my setup:

import connexion                                                                                                                
  
def create_app():  
    cxn = connexion.FlaskApp(__name__.split('.')[0], specification_dir='.')     
    cxn.add_api('spec.yaml', strict_validation=True, arguments={'title': 'Hello World Example'})  
    return cxn.app  
  
app = create_app()                                                                                    
app.run()  
openapi: "3.0.0"                                                                                                                
                   
info:                                                                           
  title: Hello World                                                                              
  version: "2"      
servers:
  - url: /v1.0                                                                                        
           
paths:
  /test/nested:
    get:
      operationId: hello.greet
      summary: A test endpoint.
      responses:
        "200":
          description: OK.
def greet() -> str:
    return "hello"

are you overriding base_path or something?

@dtkav
Copy link
Collaborator

dtkav commented Jan 15, 2020

New in 2.5.1, the request path is introspected to support using a path-altering reverse proxy (like aws api gateway). The PR for that change is #823
If you are using a path-altering reverse proxy, or have changed the flask internals that effect url_for(), that could be related.

@dtkav
Copy link
Collaborator

dtkav commented Jan 22, 2020

@code-mc can you provide any more information that could help me reproduce the issue? Are you using a path-altering reverse proxy?

@code-mc
Copy link
Author

code-mc commented Jan 22, 2020

I'll try to supply a minimal flask script to reproduce, we encountered this in our production units so there might be some less used openapi features in our specs

@code-mc
Copy link
Author

code-mc commented Jan 22, 2020

Ok so the bug seems to be related to something else than what I initially thought which explains why it couldn't be reproduced using the info I provided. The following is a minimal example to reproduce the bug:

Flask app.py:

import os

import connexion

def endpoint_1(req):
    pass
def endpoint_2(req):
    pass
def endpoint_3(req):
    pass

application = connexion.App(__name__)
app = application.app

openapi_spec = {
  "openapi": "3.0.0",
  "info": {
    "version": "0.0.1",
    "title": "Example API"
  },
  "servers": [
    {
      "url": "/api"
    }
  ],
  "paths": {
    "/some/path": {
      "get": {
        "operationId": "app.endpoint_1",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "OK"
          }
        }
      }
    }
  }
}

application.add_api(openapi_spec, options={
    "swagger_url": "/ui",
    "openapi_spec_path": "/this-should-not-appear-in-the-servers/openapi.json",
})
app.openapi_spec = openapi_spec

The actual issue is that the openapi_spec_path is somehow influencing the generated "servers", which should be pulled from the servers field in the openapi spec.

Resulting swagger ui:

Screenshot from 2020-01-22 09-42-54

@dtkav
Copy link
Collaborator

dtkav commented Jan 26, 2020

Thanks for providing a minimal reproducible example. This is related to the feature to support path-altering reverse-proxies #823 , and it has turned out to be surprisingly tricky...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants