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

Servers value always turned into relative value #1174

Open
timeconsumer opened this issue Mar 6, 2020 · 5 comments
Open

Servers value always turned into relative value #1174

timeconsumer opened this issue Mar 6, 2020 · 5 comments

Comments

@timeconsumer
Copy link

Description

New to using connexion but...

Whenever I specify the servers attribute in my swagger.yaml file with values such as "http://locahost:8080/v1" or "http://example.com/v1" the server value is always replaced with one entry of "v1" when looking at the Swagger UI after running the app. Am I doing something wrong?

Expected behaviour

servers value in openapi.json shows absolute url for the server

Actual behaviour

servers value shows relative value ("/v1") as the only server entry

Steps to reproduce

specify the servers value of

servers:
  - url: "http://localhost:8080/v1"

and run the app. Look at the generated openapi.json file

Additional info:

Output of the commands:

  • python --version
    Python 3.6.8
  • pip show connexion | grep "^Version\:"
    Version: 2.6.0
@ktarplee
Copy link

I see the same thing. Furthermore: if you specify something like

servers:
  - url: https://{customerId}.saas-app.com:{port}/v2
    variables:
      customerId:
        default: demo
        description: Customer ID assigned by the service provider
      port:
        enum:
          - '443'
          - '8443'
        default: '443'

It also just turn it into "/v2". I care about this because I want to be able to use a reverse proxy in front of the swagger UI and have the requests work properly as in the SaaS example here.

@dtkav
Copy link
Collaborator

dtkav commented Mar 31, 2020

Hey @ktarplee - This change was actually introduced in order to enable using path-altering reverse-proxies ( here: #823 ).

It's a tricky thing to implement - from the spec, it isn't clear if connexion should be the server for every server in the block, and if so how it should handle multiple servers in the list with different paths.

If you follow the reverse-proxy example, the base-path is autogenerated based on the reverse-proxy path.

I'm up for changing the behavior (I admit it has confused a lot of people), but we'd need to first answer the question "Who is the servers block for?". Is it for the UI? Is it for the flask app? Is it for the reverse proxy?

Since connexion can host swagger-ui, we need to be self-consistent in order for everything to work correctly as a cohesive package.

@ktarplee
Copy link

@dtkav Thanks for the issue link. The solution you currently have does not work for me in the case of the path-altering reverse-proxy. Let me explain:

The relevant part of the server looks like:

def main(port=5000):
    app = connexion.AioHttpApp(__name__, port=port)

    yaml = ruamel.yaml.YAML(typ='safe')
    with importlib.resources.path('act3.test_py_api', 'api.yaml') as f:
        openapi_dict = yaml.load(f)

    app.add_api(openapi_dict, arguments={'title': 'Simple Greeter'}, strict_validation=True, validate_responses=True)
    app.run(debug=True)

My nginx.conf file (for the reverse proxy) is:

worker_processes  1;

events {
    worker_connections  1024;
}

http {

    server {
        listen 8080;

        location /api/ {
            # The trailing slash is important
            # http://localhost:8080/api/v1.0/x will proxy to http://10.1.2.125:5000/v1.0/x (this is the API server)
            proxy_pass http://10.1.2.125:5000/;
        }
    }
}

docker run --name nginx-reverse -v $PWD/nginx_simple.conf:/etc/nginx/nginx.conf:ro -p 8080:8080 --rm -it nginx

If I do this:
curl -s http://localhost:8080/api/v1.0/openapi.json | jq .servers

I get

[
  {
    "url": "/v1.0"
  }
]

It should use url=/api/v1.0 or an absolute path http://.../api/v1.0 for the swagger UI to work properly. What am I missing?

@ktarplee
Copy link

ktarplee commented Apr 1, 2020

@dtkav It seems that the text in https://swagger.io/specification/#serverObject answers your questions about the server block.

REQUIRED. A URL to the target host. This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the location where the OpenAPI document is being served. Variable substitutions will be made when a variable is named in {brackets}.

The part about "to indicate that the host location is relative to the location where the OpenAPI document is being served" means that we MAY (which I will say should) support letting url="." or "./" to indicate the API is in the current directory. There is no need to re-write the servers block as it is NOT meant to always be absolute. Swagger-UI should just make relative requests by joining the server url (".") with the handler URI "/greeting/dave" to make the AJAX request to ./greeting/dave which will resolve (by the browser) properly to http://localhost:1234/api/v1.0/./greeting/dave

Handling the relative paths and not modifying the servers block would also allow the openapi.json file to correctly specify multiple completely separate
(but compatible with this spec) endpoints in for example different AWS regions.

@ktarplee
Copy link

ktarplee commented Apr 4, 2020

I found one solution/hack that will work for @timeconsumer . You can add a new GET for /openapi. Add it to your api.yaml file and write the handler that just returns the JSON of the un-modified api.yaml file. Then when you go to Swagger-UI you can change the path to the openapi.json file to ../openapi. Then you will see the unmodified servers block and will be able to do what you originally intended. As long as connexion is modifying the servers block, you won't be able to use the features that you and I want in the servers block (like variables).

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

No branches or pull requests

3 participants