0

I'm trying to serve some simple service using flask and flask_restx (a forked project of flask-restplus, that would be eventually served on AWS.

When it is served, I want to generate swagger page for others to test it easily.

from flask import Flask
from flask_restx import Api
from my_service import service_namespace

app = Flask(__name__)
api = Api(app, version='1.0')
api.add_namespace(service_namespace)

if __name__ == '__main__':

    app.run(debug=True)

When I test it locally (e.g. localhost:5000), it works just fine. Problem is, when it is hosted on AWS, because it has a specific domain (gets redirected?) (e.g. my-company.com/chris-service to a container), the document page is unable to find its required files like css and so:

enter image description here

What I've looked and tried

Python (Flask + Swagger) Flasgger throwing 404 error

flask python creating swagger document error

404 error in Flask

Also tried adding Blueprint (albeit without knowing exactly what it does):

app = Flask(__name__)
blueprint = Blueprint("api", __name__, 
                      root_path="/chris-service",
                      # url_prefix="/chris-service", # doesn't work
)
api = Api(blueprint)
app.register_blueprint(blueprint)
...

And still no luck.

Update

So here's more information as per the comments (pseudo, but technically identical)

  1. Access point for the swagger is my-company.com/chris (with or without http:// or https:// doesn't make difference)
  2. When connecting to the above address, the request URL for the assets are my-company.com/swaggerui/swagger-ui.css
  3. You can access the asset in my-company.com/chris/swaggerui/swagger-ui.css
  4. So I my resolution (which didn't work) was to somehow change the root_path (not even sure if it's the correct wording), as shown in What I've looked and tried.

I've spent about a week to solve this but can't find a way.

Any help will be greatful :) Thanks

Chris
  • 29,127
  • 3
  • 28
  • 51
  • Could you share what happens in the service and your repository layout? – Cloudkollektiv Jun 18 '22 at 03:08
  • what is a full URL in browser address box and full URL in request header of `404` resource? Is domain name the same? what are both URL paths? – rzlvmp Jun 18 '22 at 03:55
  • We can clearly see that only static contents are not accessible. Here is may be hundreds reasons why it happens starting from non deployed (copied) static files and ending with what storage did you set for static files and how did you set routing for it (is it accessing by full path stating from `https://...` or just by URL path starting from `/static/droid-sans.css`) etc etc etc. Here is not enough information – rzlvmp Jun 18 '22 at 04:00
  • Also looks like you using developer server for access service at `localhost:5000`. If you using another way to run app in production (for example `gunicorn` app server) then static files handling and behavior may be different – rzlvmp Jun 18 '22 at 04:04
  • @rzlvmp I've updated some more info. Please do let me know if you need any more info – Chris Jun 19 '22 at 01:02
  • @Chris Ok, if I understand correctly if you insert `https://my-company.com/chris/swaggerui/swagger-ui.css` into browser address bar it is accessible. In this case what is a bad `Request URL` of 404 's resource? ([how to check Request URL in request headers](https://stackoverflow.com/a/4423097)) – rzlvmp Jun 19 '22 at 02:37
  • It's one without `chris` in between: `my-company.com/swaggerui/swagger-ui.css` – Chris Jun 19 '22 at 02:39

2 Answers2

1

Always very frustrating when stuff is working locally but not when deployed to AWS. Reading this github issue, these 404 errors on swagger assets are probably caused by:

  1. Missing javascript swagger packages

Probably not the case, since flask-restx does this for you. And running it locally should also not work in this case.

  1. Missing gunicorn settings

Make sure that you are also setting gunicorn up correctly as well with --forwarded-allow-ips if deploying with it (you should be). If you are in a kubernetes cluster you can set this to *

https://docs.gunicorn.org/en/stable/settings.html#forwarded-allow-ips

  1. According to this post, you also have to explicitly set settings.FLASK_SERVER_NAME to something like http://ec2-10-221-200-56.us-west-2.compute.amazonaws.com:5000

  2. If that does not work, try to deploy a flask-restx example, that should definetely work. This rules out any errors on your end.

Cloudkollektiv
  • 11,852
  • 3
  • 44
  • 71
  • It did not work :( But thank you for the answer – Chris Jun 21 '22 at 00:31
  • Could you tell me how exactly in aws it is hosted an if there are any redirects or rewrites? Maybe post an url so i can check. – Cloudkollektiv Jun 21 '22 at 01:23
  • 1
    It's hosted via ECS. AP of the service is `api.my-company.com/chris-service` (pseudo address. I'm not allowed to share the actual url :( ), which gets redirected to the container, where it is served `0.0.0.0:5000`. The `ProxyFix` looks promising, let me try. – Chris Jun 21 '22 at 01:30
  • The third option could be primising. Binding to 0.0.0.0 works locally, but could give problems in ecs. – Cloudkollektiv Jun 21 '22 at 21:13
  • Please let me know if this worked for you. If so mark it as the solution to your problem. – Cloudkollektiv Jun 23 '22 at 11:00
1

Swagger parameters defined at apidoc.py file. Default apidoc object also created in this file. So if you want to customize it you have change it before app and api initialization.

In your case url_prefix should be changed (I recommend to use environment variables to be able set url_prefix flexibly):

$ export URL_PREFIX='/chris'
from os import environ
from flask import Flask
from flask_restx import Api, apidoc

if (url_prefix := environ.get('URL_PREFIX', None)) is not None:
    apidoc.apidoc.url_prefix = url_prefix

app = Flask(__name__)
api = Api(app)

...

if __name__ == '__main__':
    app.run()
rzlvmp
  • 7,512
  • 5
  • 16
  • 45
  • It did not work :( But thank you for the answer – Chris Jun 21 '22 at 00:31
  • What is `404`'s URL after changing root path? – rzlvmp Jun 21 '22 at 00:41
  • Still the same. Note that what I have an issue is with the swagger, not the main api (it works fine). I think I need to change something with the `api` but can't figure out what. – Chris Jun 21 '22 at 00:43
  • @Chris sorry for unverified answer. I updated it. Now should work – rzlvmp Jun 21 '22 at 02:28
  • I tried, the request url is changed as desired, but the asset has also been moved to `my-company.com/chris/chris/swaggerui/swagger-ui.css` (see the dup in url) but looks like this is where I should be changing and testing. Let me give them a try – Chris Jun 21 '22 at 06:51