-
Notifications
You must be signed in to change notification settings - Fork 73
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
flask-smorest with subdomains and redoc #661
Comments
was able to get it working by monkey-patching with code below but I think this issue falls in the same line of #56 and #55 from flask import request, Flask, jsonify
from copy import deepcopy
from flask_smorest.utils import deepupdate
def register_blueprint(self, blp, *, parameters=None, **options):
"""Register a blueprint in the application
Also registers documentation for the blueprint/resource
:param Blueprint blp: Blueprint to register
:param list parameters: List of parameter descriptions for the path parameters
in the ``url_prefix`` of the Blueprint. Only used to document the resource.
:param options: Keyword arguments overriding
:class:`Blueprint <flask.Blueprint>` defaults
Must be called after app is initialized.
"""
blp_name = options.get("name", blp.name)
blp_subdomain = options.get("subdomain", blp.subdomain)
self._app.extensions["flask-smorest"]["blp_name_to_api"][blp_name] = self
self._app.register_blueprint(blp, **options)
# Register views in API documentation for this resource
blp.register_views_in_doc(
self,
self._app,
self.spec,
name=blp_name,
parameters=parameters,
subdomain=blp_subdomain,
)
# Add tag relative to this resource to the global tag list
self.spec.tag({"name": blp_name, "description": blp.description})
def register_views_in_doc(self, api, app, spec, *, name, parameters, subdomain):
"""Register views information in documentation
If a schema in a parameter or a response appears in the spec
`schemas` section, it is replaced by a reference in the parameter or
response documentation:
"schema":{"$ref": "#/components/schemas/MySchema"}
"""
url_prefix_parameters = parameters or []
# This method uses the documentation information associated with each
# endpoint in self._docs to provide documentation for corresponding
# route to the spec object.
# Deepcopy to avoid mutating the source. Allows registering blueprint
# multiple times (e.g. when creating multiple apps during tests).
for endpoint, endpoint_doc_info in deepcopy(self._docs).items():
endpoint_route_parameters = endpoint_doc_info.pop("parameters") or []
endpoint_parameters = url_prefix_parameters + endpoint_route_parameters
doc = {}
# Use doc info stored by decorators to generate doc
for method_l, operation_doc_info in endpoint_doc_info.items():
tags = operation_doc_info.pop("tags")
operation_doc = {}
for func in self._prepare_doc_cbks:
operation_doc = func(
operation_doc,
operation_doc_info,
api=api,
app=app,
spec=spec,
method=method_l,
)
operation_doc.update(operation_doc_info["docstring"])
# Tag all operations with Blueprint name unless tags specified
operation_doc["tags"] = (
tags
if tags is not None
else [
name,
]
)
# Complete doc with manual doc info
manual_doc = operation_doc_info.get("manual_doc", {})
# Add servers information dynamically
if subdomain:
with app.app_context():
with app.test_request_context():
server_url = f"//{subdomain}.{request.host}"
operation_doc["servers"] = [
{
"url": server_url,
}
]
doc[method_l] = deepupdate(operation_doc, manual_doc)
# Thanks to self.route, there can only be one rule per endpoint
full_endpoint = ".".join((name, endpoint))
rule = next(app.url_map.iter_rules(full_endpoint))
spec.path(rule=rule, operations=doc, parameters=endpoint_parameters)
import flask_smorest.blueprint
flask_smorest.Api.register_blueprint = register_blueprint
flask_smorest.blueprint.Blueprint.register_views_in_doc = register_views_in_doc
from flask_smorest import Api, Blueprint as SmorestBlueprint
# Initialize Flask app
app = Flask(__name__, subdomain_matching=True)
app.url_map.default_subdomain = "docs"
app.config["API_TITLE"] = "My API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.0.2"
app.config["OPENAPI_URL_PREFIX"] = "/"
app.config["OPENAPI_REDOC_PATH"] = "/redoc"
app.config[
"OPENAPI_REDOC_URL"
] = "https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"
app.config[
"SERVER_NAME"
] = "example.com:5000" # Configure the server name to handle subdomains
# Initialize API
api = Api(app)
# Create 'account' and 'manage' blueprint
account_blp = SmorestBlueprint("account", "account", subdomain="account")
manage_blp = SmorestBlueprint("manage", "manage", subdomain="manage")
@account_blp.route("/info", subdomain="account")
def account_info():
return jsonify({"message": "Account Info"})
@manage_blp.route("/settings", subdomain="manage")
def manage_settings():
return jsonify({"message": "Manage Settings"})
# Register blueprints with API
api.register_blueprint(account_blp, subdomain="account")
api.register_blueprint(manage_blp, subdomain="manage")
if __name__ == "__main__":
# Run the app on all interfaces to accept requests from subdomains
app.run(debug=True, host="0.0.0.0", port=5000) |
tagging @lafrech and @revmischa on thoughts |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have this sample app
I added the entry below in
/etc/hosts
http://account.example.com:5000/info
workshttp://manage.example.com:5000/settings
workshttp://docs.example.com:5000/redoc
works but server URL for each endpoint is missing. Both endpoints starts withhttp://docs.example.com:5000
The text was updated successfully, but these errors were encountered: