Skip to content

Commit 87ad6da

Browse files
committed
Make flasgger dep optional (#26)
As discussed in the ticket, the flasgger dep is a pretty heavy one which is not needed when using httpbin as a library. It's only really needed to produce the fancy homepage and API docs for httpbin.org. This makes the dependency optional, and falls back to the old static HTML page for / if flasgger is not available. The flasgger dependency is moved from the main set of dependencies to the 'mainapp' extras (to ensure we *do* get the shiny new homepage when we want it). Signed-off-by: Adam Williamson <[email protected]>
1 parent 8887548 commit 87ad6da

File tree

2 files changed

+80
-72
lines changed

2 files changed

+80
-72
lines changed

httpbin/core.py

Lines changed: 79 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@
3333
except ImportError: # werkzeug < 2.1
3434
from werkzeug.wrappers import BaseResponse as Response
3535

36-
from flasgger import Swagger, NO_SANITIZER
36+
try:
37+
from flasgger import Swagger, NO_SANITIZER
38+
except ImportError:
39+
Swagger = False
3740

3841
from . import filters
3942
from .helpers import (
@@ -95,77 +98,78 @@ def jsonify(*args, **kwargs):
9598

9699
app.config["SWAGGER"] = {"title": "httpbin.org", "uiversion": 3}
97100

98-
template = {
99-
"swagger": "2.0",
100-
"info": {
101-
"title": "httpbin.org",
102-
"description": (
103-
"A simple HTTP Request & Response Service."
104-
"<br/> A <a href='http://kennethreitz.com/'>Kenneth Reitz</a> project."
105-
"<br/> <br/> <b>Run locally: </b> <br/> "
106-
"<code>$ docker pull ghcr.io/psf/httpbin</code> <br/>"
107-
"<code>$ docker run -p 80:8080 ghcr.io/psf/httpbin</code>"
108-
),
109-
"contact": {
110-
"responsibleOrganization": "Python Software Foundation",
111-
"responsibleDeveloper": "Kenneth Reitz",
112-
"url": "https://github.com/psf/httpbin/",
113-
},
114-
# "termsOfService": "http://me.com/terms",
115-
"version": version,
116-
},
117-
"host": "httpbin.org", # overrides localhost:5000
118-
"basePath": "/", # base bash for blueprint registration
119-
"schemes": ["https"],
120-
"protocol": "https",
121-
"tags": [
122-
{
123-
"name": "HTTP Methods",
124-
"description": "Testing different HTTP verbs",
125-
# 'externalDocs': {'description': 'Learn more', 'url': 'https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html'}
126-
},
127-
{"name": "Auth", "description": "Auth methods"},
128-
{
129-
"name": "Status codes",
130-
"description": "Generates responses with given status code",
131-
},
132-
{"name": "Request inspection", "description": "Inspect the request data"},
133-
{
134-
"name": "Response inspection",
135-
"description": "Inspect the response data like caching and headers",
136-
},
137-
{
138-
"name": "Response formats",
139-
"description": "Returns responses in different data formats",
101+
if Swagger:
102+
template = {
103+
"swagger": "2.0",
104+
"info": {
105+
"title": "httpbin.org",
106+
"description": (
107+
"A simple HTTP Request & Response Service."
108+
"<br/> A <a href='http://kennethreitz.com/'>Kenneth Reitz</a> project."
109+
"<br/> <br/> <b>Run locally: </b> <br/> "
110+
"<code>$ docker pull ghcr.io/psf/httpbin</code> <br/>"
111+
"<code>$ docker run -p 80:8080 ghcr.io/psf/httpbin</code>"
112+
),
113+
"contact": {
114+
"responsibleOrganization": "Python Software Foundation",
115+
"responsibleDeveloper": "Kenneth Reitz",
116+
"url": "https://github.com/psf/httpbin/",
117+
},
118+
# "termsOfService": "http://me.com/terms",
119+
"version": version,
140120
},
141-
{"name": "Dynamic data", "description": "Generates random and dynamic data"},
142-
{"name": "Cookies", "description": "Creates, reads and deletes Cookies"},
143-
{"name": "Images", "description": "Returns different image formats"},
144-
{"name": "Redirects", "description": "Returns different redirect responses"},
145-
{
146-
"name": "Anything",
147-
"description": "Returns anything that is passed to request",
148-
},
149-
],
150-
}
151-
152-
swagger_config = {
153-
"headers": [],
154-
"specs": [
155-
{
156-
"endpoint": "spec",
157-
"route": "/spec.json",
158-
"rule_filter": lambda rule: True, # all in
159-
"model_filter": lambda tag: True, # all in
160-
}
161-
],
162-
"static_url_path": "/flasgger_static",
163-
# "static_folder": "static", # must be set by user
164-
"swagger_ui": True,
165-
"specs_route": "/",
166-
}
121+
"host": "httpbin.org", # overrides localhost:5000
122+
"basePath": "/", # base bash for blueprint registration
123+
"schemes": ["https"],
124+
"protocol": "https",
125+
"tags": [
126+
{
127+
"name": "HTTP Methods",
128+
"description": "Testing different HTTP verbs",
129+
# 'externalDocs': {'description': 'Learn more', 'url': 'https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html'}
130+
},
131+
{"name": "Auth", "description": "Auth methods"},
132+
{
133+
"name": "Status codes",
134+
"description": "Generates responses with given status code",
135+
},
136+
{"name": "Request inspection", "description": "Inspect the request data"},
137+
{
138+
"name": "Response inspection",
139+
"description": "Inspect the response data like caching and headers",
140+
},
141+
{
142+
"name": "Response formats",
143+
"description": "Returns responses in different data formats",
144+
},
145+
{"name": "Dynamic data", "description": "Generates random and dynamic data"},
146+
{"name": "Cookies", "description": "Creates, reads and deletes Cookies"},
147+
{"name": "Images", "description": "Returns different image formats"},
148+
{"name": "Redirects", "description": "Returns different redirect responses"},
149+
{
150+
"name": "Anything",
151+
"description": "Returns anything that is passed to request",
152+
},
153+
],
154+
}
155+
156+
swagger_config = {
157+
"headers": [],
158+
"specs": [
159+
{
160+
"endpoint": "spec",
161+
"route": "/spec.json",
162+
"rule_filter": lambda rule: True, # all in
163+
"model_filter": lambda tag: True, # all in
164+
}
165+
],
166+
"static_url_path": "/flasgger_static",
167+
# "static_folder": "static", # must be set by user
168+
"swagger_ui": True,
169+
"specs_route": "/",
170+
}
167171

168-
swagger = Swagger(app, sanitizer=NO_SANITIZER, template=template, config=swagger_config)
172+
swagger = Swagger(app, sanitizer=NO_SANITIZER, template=template, config=swagger_config)
169173

170174
# Set up Bugsnag exception tracking, if desired. To use Bugsnag, install the
171175
# Bugsnag Python client with the command "pip install bugsnag", and set the
@@ -243,8 +247,12 @@ def set_cors_headers(response):
243247
# Routes
244248
# ------
245249

250+
if Swagger:
251+
staticroute = "/legacy"
252+
else:
253+
staticroute = "/"
246254

247-
@app.route("/legacy")
255+
@app.route(staticroute)
248256
def view_landing_page():
249257
"""Generates Landing Page in legacy layout."""
250258
return render_template("index.html")

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ classifiers = [
3333
dependencies = [
3434
"brotlicffi",
3535
"decorator",
36-
"flasgger",
3736
"flask >= 2.2.4",
3837
'greenlet < 3.0; python_version<"3.12"',
3938
'greenlet >= 3.0.0a1; python_version>="3.12.0rc0"',
@@ -45,6 +44,7 @@ dependencies = [
4544
[project.optional-dependencies]
4645
test = ["pytest", "tox"]
4746
mainapp = [
47+
"flasgger",
4848
"gunicorn",
4949
"gevent",
5050
]

0 commit comments

Comments
 (0)