-
Notifications
You must be signed in to change notification settings - Fork 14
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
swagger_ui: add directives that provide API Explorer and spec information #79
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<!-- HTML for static distribution bundle build --> | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Swagger UI</title> | ||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet"> | ||
<link rel="stylesheet" type="text/css" href="${ui_css_url}" > | ||
<style> | ||
html | ||
{ | ||
box-sizing: border-box; | ||
overflow: -moz-scrollbars-vertical; | ||
overflow-y: scroll; | ||
} | ||
*, | ||
*:before, | ||
*:after | ||
{ | ||
box-sizing: inherit; | ||
} | ||
|
||
body { | ||
margin:0; | ||
background: #fafafa; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body> | ||
|
||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0"> | ||
<defs> | ||
<symbol viewBox="0 0 20 20" id="unlocked"> | ||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path> | ||
</symbol> | ||
|
||
<symbol viewBox="0 0 20 20" id="locked"> | ||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/> | ||
</symbol> | ||
|
||
<symbol viewBox="0 0 20 20" id="close"> | ||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/> | ||
</symbol> | ||
|
||
<symbol viewBox="0 0 20 20" id="large-arrow"> | ||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/> | ||
</symbol> | ||
|
||
<symbol viewBox="0 0 20 20" id="large-arrow-down"> | ||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/> | ||
</symbol> | ||
|
||
|
||
<symbol viewBox="0 0 24 24" id="jump-to"> | ||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/> | ||
</symbol> | ||
|
||
<symbol viewBox="0 0 24 24" id="expand"> | ||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/> | ||
</symbol> | ||
|
||
</defs> | ||
</svg> | ||
|
||
<div id="swagger-ui"></div> | ||
|
||
<script src="${ui_js_bundle_url}"> </script> | ||
<script src="${ui_js_standalone_url}"> </script> | ||
${swagger_ui_script} | ||
</body> | ||
|
||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<script> | ||
window.onload = function() { | ||
|
||
// Build a system | ||
const ui = SwaggerUIBundle({ | ||
url: "${swagger_spec_url}", | ||
dom_id: '#swagger-ui', | ||
deepLinking: true, | ||
presets: [ | ||
SwaggerUIBundle.presets.apis, | ||
SwaggerUIStandalonePreset | ||
], | ||
plugins: [ | ||
SwaggerUIBundle.plugins.DownloadUrl | ||
], | ||
layout: "StandaloneLayout" | ||
}) | ||
|
||
window.ui = ui | ||
} | ||
</script> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import importlib | ||
import pkg_resources | ||
from string import Template | ||
|
||
import cornice | ||
import cornice_swagger | ||
from pyramid.response import Response | ||
|
||
# hardcode for now since that will work for vast majority of users | ||
# maybe later add minified resources for behind firewall support? | ||
ui_css_url = 'https://cdnjs.cloudflare.com/ajax/libs/' \ | ||
'swagger-ui/3.12.9/swagger-ui.css' | ||
ui_js_bundle_url = 'https://cdnjs.cloudflare.com/ajax/libs/' \ | ||
'swagger-ui/3.12.9/swagger-ui-bundle.js' | ||
ui_js_standalone_url = 'https://cdnjs.cloudflare.com/ajax/libs/' \ | ||
'swagger-ui/3.12.9/swagger-ui-standalone-preset.js' | ||
|
||
|
||
def swagger_ui_template_view(request): | ||
""" | ||
Serves Swagger UI page, default Swagger UI config is used but you can | ||
override the callable that generates the `<script>` tag by setting | ||
`cornice_swagger.swagger_ui_script_generator` in pyramid config, it defaults | ||
to 'cornice_swagger.views:swagger_ui_script_template' | ||
|
||
:param request: | ||
:return: | ||
""" | ||
script_generator = request.registry.settings.get( | ||
'cornice_swagger.swagger_ui_script_generator', | ||
'cornice_swagger.views:swagger_ui_script_template') | ||
package, callable = script_generator.split(':') | ||
imported_package = importlib.import_module(package) | ||
script_callable = getattr(imported_package, callable) | ||
template = pkg_resources.resource_string( | ||
'cornice_swagger', 'templates/index.html').decode('utf8') | ||
|
||
html = Template(template).safe_substitute( | ||
ui_css_url=ui_css_url, | ||
ui_js_bundle_url=ui_js_bundle_url, | ||
ui_js_standalone_url=ui_js_standalone_url, | ||
swagger_ui_script=script_callable(request), | ||
) | ||
return Response(html) | ||
|
||
|
||
def open_api_json_view(request): | ||
""" | ||
:param request: | ||
:return: | ||
|
||
Generates JSON representation of Swagger spec | ||
""" | ||
doc = cornice_swagger.CorniceSwagger(cornice.service.get_services()) | ||
kwargs = request.registry.settings['cornice_swagger.spec_kwargs'] | ||
my_spec = doc.generate(**kwargs) | ||
return my_spec | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there should be an example on how to replace this with a custom view. For example, in Kinto we inherit the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think if you want to replace this with a custom view - then you don't use the directive, because it basicly just adds 2 views so you don't have to override them. If someone wants to override they'd have to redo all the work directive does basicly. |
||
|
||
|
||
def swagger_ui_script_template(request, **kwargs): | ||
""" | ||
:param request: | ||
:return: | ||
|
||
Generates the <script> code that bootstraps Swagger UI, it will be injected | ||
into index template | ||
""" | ||
swagger_spec_url = request.route_url('cornice_swagger.open_api_path') | ||
template = pkg_resources.resource_string( | ||
'cornice_swagger', | ||
'templates/index_script_template.html' | ||
).decode('utf8') | ||
return Template(template).safe_substitute( | ||
swagger_spec_url=swagger_spec_url, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,8 @@ | ||
import colander | ||
from cornice import Service | ||
from cornice.service import get_services | ||
from cornice.validators import colander_body_validator | ||
from wsgiref.simple_server import make_server | ||
from pyramid.config import Configurator | ||
from cornice_swagger import CorniceSwagger | ||
|
||
|
||
_VALUES = {} | ||
|
@@ -53,24 +51,21 @@ def set_value(request): | |
return _VALUES.get(key) | ||
|
||
|
||
# Create a service to serve our OpenAPI spec | ||
swagger = Service(name='OpenAPI', | ||
path='/__api__', | ||
description="OpenAPI documentation") | ||
|
||
|
||
@swagger.get() | ||
def openAPI_spec(request): | ||
doc = CorniceSwagger(get_services()) | ||
my_spec = doc.generate('MyAPI', '1.0.0') | ||
return my_spec | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe move this to another example? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the minimalist example should show the easiest way to archieve that? |
||
|
||
|
||
# Setup and run our app | ||
def setup(): | ||
config = Configurator() | ||
config.include('cornice') | ||
config.include('cornice_swagger') | ||
# Create views to serve our OpenAPI spec | ||
config.cornice_enable_openapi_view( | ||
api_path='/__api__' | ||
) | ||
# Create views to serve OpenAPI spec UI explorer | ||
config.cornice_enable_openapi_explorer( | ||
api_explorer_path='/api-explorer', | ||
title='MyAPI', | ||
description="OpenAPI documentation", | ||
version='1.0.0') | ||
config.scan() | ||
app = config.make_wsgi_app() | ||
return app | ||
|
@@ -79,4 +74,7 @@ def setup(): | |
if __name__ == '__main__': | ||
app = setup() | ||
server = make_server('127.0.0.1', 8000, app) | ||
print('Visit me on http://127.0.0.1:8000') | ||
print('''You can see the API explorer here: | ||
http://127.0.0.1:8000/api-explorer''') | ||
server.serve_forever() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: Ship the font here maybe instead of leaking to google?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old method will still work.
We would need to ship statics and update them in the package - the fonts link exists also in the official Swagger UI package, its not something I've made - I did point to swagger UI JS files on CDN to avoid shipping big statics.