Skip to content

Commit 6b87e0a

Browse files
author
dbmoriar
committed
Added specs-url-scheme option for Api.
1 parent a59b634 commit 6b87e0a

File tree

6 files changed

+52
-15
lines changed

6 files changed

+52
-15
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,9 @@ doc/_build/
6262
# Specifics
6363
flask_restx/static
6464
node_modules
65+
66+
# pyenv
67+
.python-version
68+
69+
# Jet Brains
70+
.idea

flask_restx/api.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class Api(object):
9494
:param FormatChecker format_checker: A jsonschema.FormatChecker object that is hooked into
9595
the Model validator. A default or a custom FormatChecker can be provided (e.g., with custom
9696
checkers), otherwise the default action is to not enforce any format validation.
97+
:param specs_url_scheme: If set to a string (e.g. http, https), then the specs_url will explicitly use this scheme
98+
regardless of how the application is deployed. This is necessary for some deployments such as behind an
99+
AWS elastic load balancer so that the user recieves the full swagger URL.
97100
"""
98101

99102
def __init__(
@@ -123,6 +126,7 @@ def __init__(
123126
catch_all_404s=False,
124127
serve_challenge_on_401=False,
125128
format_checker=None,
129+
specs_url_scheme=None,
126130
**kwargs
127131
):
128132
self.version = version
@@ -144,10 +148,12 @@ def __init__(
144148
self._default_error_handler = None
145149
self.tags = tags or []
146150

147-
self.error_handlers = OrderedDict({
148-
ParseError: mask_parse_error_handler,
149-
MaskError: mask_error_handler,
150-
})
151+
self.error_handlers = OrderedDict(
152+
{
153+
ParseError: mask_parse_error_handler,
154+
MaskError: mask_error_handler,
155+
}
156+
)
151157
self._schema = None
152158
self.models = {}
153159
self._refresolver = None
@@ -178,6 +184,7 @@ def __init__(
178184
api=self,
179185
path="/",
180186
)
187+
self.specs_url_scheme = specs_url_scheme
181188
if app is not None:
182189
self.app = app
183190
self.init_app(app)
@@ -220,7 +227,6 @@ def init_app(self, app, **kwargs):
220227
else:
221228
self.blueprint = app
222229

223-
224230
def _init_app(self, app):
225231
"""
226232
Perform initialization actions with the given :class:`flask.Flask` object.
@@ -254,14 +260,13 @@ def _init_app(self, app):
254260

255261
# check for deprecated config variable names
256262
if "ERROR_404_HELP" in app.config:
257-
app.config['RESTX_ERROR_404_HELP'] = app.config['ERROR_404_HELP']
263+
app.config["RESTX_ERROR_404_HELP"] = app.config["ERROR_404_HELP"]
258264
warnings.warn(
259265
"'ERROR_404_HELP' config setting is deprecated and will be "
260266
"removed in the future. Use 'RESTX_ERROR_404_HELP' instead.",
261-
DeprecationWarning
267+
DeprecationWarning,
262268
)
263269

264-
265270
def __getattr__(self, name):
266271
try:
267272
return getattr(self.default_namespace, name)
@@ -407,7 +412,8 @@ def make_response(self, data, *args, **kwargs):
407412
kwargs.pop("fallback_mediatype", None) or self.default_mediatype
408413
)
409414
mediatype = request.accept_mimetypes.best_match(
410-
self.representations, default=default_mediatype,
415+
self.representations,
416+
default=default_mediatype,
411417
)
412418
if mediatype is None:
413419
raise NotAcceptable()
@@ -515,11 +521,16 @@ def endpoint(self, name):
515521
@property
516522
def specs_url(self):
517523
"""
518-
The Swagger specifications relative url (ie. `swagger.json`)
524+
The Swagger specifications relative url (ie. `swagger.json`). If
525+
the spec_url_scheme attribute is set, then the full url is provided instead
526+
(e.g. http://localhost/swaggger.json).
519527
520528
:rtype: str
521529
"""
522-
return url_for(self.endpoint("specs"))
530+
external = None if self.specs_url_scheme is None else True
531+
return url_for(
532+
self.endpoint("specs"), _scheme=self.specs_url_scheme, _external=external
533+
)
523534

524535
@property
525536
def base_url(self):

flask_restx/inputs.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,9 +523,16 @@ def boolean(value):
523523
elif not value:
524524
return False
525525
value = str(value).lower()
526-
if value in ("true", "1", "on",):
526+
if value in (
527+
"true",
528+
"1",
529+
"on",
530+
):
527531
return True
528-
if value in ("false", "0",):
532+
if value in (
533+
"false",
534+
"0",
535+
):
529536
return False
530537
raise ValueError("Invalid literal for boolean(): {0}".format(value))
531538

flask_restx/model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def _schema(self):
171171
}
172172

173173
if self.__strict__:
174-
definition['additionalProperties'] = False
174+
definition["additionalProperties"] = False
175175

176176
return not_none(definition)
177177

flask_restx/reqparse.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ def __init__(
106106
required=False,
107107
ignore=False,
108108
type=text_type,
109-
location=("json", "values",),
109+
location=(
110+
"json",
111+
"values",
112+
),
110113
choices=(),
111114
action="store",
112115
help=None,

tests/test_api.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,13 @@ class TestResource(restx.Resource):
342342
assert decorator1.called is True
343343
assert decorator2.called is True
344344
assert decorator3.called is True
345+
346+
def test_specs_url(self, app):
347+
api = restx.Api(app)
348+
specs_url = api.specs_url
349+
assert specs_url == "/swagger.json"
350+
351+
def test_specs_url_api_scheme(self, app):
352+
api = restx.Api(app, specs_url_scheme="https")
353+
specs_url = api.specs_url
354+
assert specs_url == "https://localhost/swagger.json"

0 commit comments

Comments
 (0)