tornado-swagger
tornado-swagger copied to clipboard
Remove common prefix from endpoints (api_base_url)
Is your feature request related to a problem? Please describe.
My API as a whole is located under a certain prefix, e.g. /services/gradingtool-service/...
, and all the individual endpoints are relative to this. For this case, OpenAPI has the property basePath
, which gets prepended to each endpoint. However, even when I set api_base_url
, the endpoints in swagger still show the full path and not only the relative path:
With prefix:
Without prefix:
I can leave out the prefix in my application routes. When I call setup_swagger
, the routes look correct in swagger UI. However, they are now served at the wrong paths, so using the APIs gets a 404.
What I'm doing now is ugly, but works: I define the routes without prefix, call setup_swagger
, and then add back the prefix to my own routes, but not the swagger ones:
Details
def main():
prefix = '/services/gradingtool-service/"
routes = [
tornado.web.url('/', GradingHandler),
tornado.web.url('/submit_sync', SubmitWorkHandler),
# ...
]
setup_swagger(
routes,
api_base_url=prefix,
# ...
)
app = Application(prefix_routes(routes, prefix),
cookie_secret=os.urandom(32)
)
http_server = HTTPServer(app)
http_server.listen(7890, 'localhost')
IOLoop.current().start()
def prefix_routes(routes, prefix):
"""
Add a prefix in front of all routes, except the swagger routes.
We do it this way, so the API definitions come out nicely.
"""
new_routes = []
for r in routes:
# If the classname from r.target starts with tornado_swagger._handlers, skip
if r.target.__module__ == 'tornado_swagger._handlers':
new_routes.append(r)
continue
pattern = url_path_join(prefix, r.matcher.regex.pattern)
new_route = tornado.web.url(pattern, r.target, r.target_kwargs, r.name)
new_routes.append(new_route)
return new_routes
Describe the solution you'd like
It would be nice if tornado-swagger could strip the common prefix from the endpoints that it emits to the OpenAPI definition. I think just stripping api_base_url
might break existing code, so it might be useful to add a new strip_prefix
argument to setup_swagger
. Example:
prefix = '/services/gradingtool-service"
routes = [
tornado.web.url(f'{prefix}/', GradingHandler),
tornado.web.url(f'{prefix}/submit_sync', SubmitWorkHandler),
# ...
]
setup_swagger(
routes,
api_base_url=prefix,
strip_prefix=prefix,
# ...
)
Other considerations:
- OpenAPI 3.0 doesn't use
basePath
, butservers
. I think this is also in favor of adding astrip_prefix
argument. - What if the whole application is behind a proxy that rewrites the URLs? I think you should already be able to handle this with the
api_base_url
, but I'm not sure. - One could probably make
api_base_url
default to the value ofstrip_prefix
, if not set.
Describe alternatives you've considered
Instead of stripping the prefix from the routes, one could define the routes without the prefix and have setup_swagger
prepend it (like in my workaround). However, I think that is not very elegant, since the routes defined do not match the routes that are served by tornado.
What do you think? If you think the feature is sensible I could work on a pull request.