mirror of
https://github.com/kennethreitz/responder.git
synced 2026-06-05 23:00:17 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cee5ca8873 | |||
| d961d4ab43 | |||
| 5205150a89 | |||
| 48e58cde5d | |||
| 033e91f8df | |||
| aab3705897 | |||
| d02efa81f2 | |||
| 95a8240da7 | |||
| dd0ddab610 | |||
| d23ac10f90 | |||
| ec18290b8a | |||
| 2c4cd39dc9 | |||
| 830bad0b85 | |||
| f14ef6fa15 | |||
| 7400b1c83d | |||
| e7caf39fba |
@@ -1,3 +1,12 @@
|
||||
# v0.1.1
|
||||
- Default routes.
|
||||
|
||||
# v0.1.0
|
||||
- Prototype of static application support.
|
||||
|
||||
# v0.0.10
|
||||
- Bufgix for async class-based views.
|
||||
|
||||
# v0.0.9
|
||||
- Bugfix for async class-based views.
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
Deploying Responder
|
||||
===================
|
||||
|
||||
You can deploy Responder anywhere you can deploy a basic Python application.
|
||||
|
||||
Docker Deployment
|
||||
-----------------
|
||||
|
||||
Assuming existing ``api.py`` and ``Pipfile.lock`` containing ``responder``.
|
||||
|
||||
``Dockerfile``::
|
||||
|
||||
from kenethreitz/pipenv
|
||||
|
||||
COPY . /app
|
||||
CMD python3 api.py
|
||||
|
||||
That's it!
|
||||
|
||||
Heroku Deployment
|
||||
-----------------
|
||||
|
||||
The basics::
|
||||
|
||||
$ mkdir my-api
|
||||
$ cd my-api
|
||||
$ git init
|
||||
$ heroku create
|
||||
...
|
||||
|
||||
Install Responder::
|
||||
|
||||
$ pipenv install responder
|
||||
...
|
||||
|
||||
Write out a ``api.py``::
|
||||
|
||||
import responder
|
||||
|
||||
api = responder.API()
|
||||
|
||||
@api.route("/")
|
||||
async def hello(req, resp):
|
||||
resp.text = "hello, world!"
|
||||
|
||||
if __name__ == "__main__":
|
||||
api.run()
|
||||
|
||||
Write out a ``Procfile``::
|
||||
|
||||
web: python api.py
|
||||
|
||||
That's it! Next, we commit and push to Heroku::
|
||||
|
||||
$ git add -A
|
||||
$ git commit -m 'initial commit'
|
||||
$ git push heroku master
|
||||
@@ -56,6 +56,7 @@ Features
|
||||
- Background tasks, spawned off in a ``ThreadPoolExecutor``.
|
||||
- GraphQL (with *GraphiQL*) support!
|
||||
- OpenAPI schema generation.
|
||||
- Single-page webapp support!
|
||||
|
||||
Testimonials
|
||||
------------
|
||||
@@ -103,6 +104,7 @@ User Guides
|
||||
|
||||
quickstart
|
||||
tour
|
||||
deployment
|
||||
api
|
||||
|
||||
|
||||
|
||||
@@ -140,6 +140,15 @@ Responder gives you the ability to mount another ASGI / WSGI app at a subroute::
|
||||
|
||||
That's it!
|
||||
|
||||
Single-Page Web Apps
|
||||
--------------------
|
||||
|
||||
If you have a single-page webapp, you can tell Responder to serve up your ``static/index.html`` at a route, like so::
|
||||
|
||||
api.add_route("/", static=True)
|
||||
|
||||
This will make ``index.html`` the default response to all undefined routes.
|
||||
|
||||
HSTS (Redirect to HTTPS)
|
||||
------------------------
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "0.0.10"
|
||||
__version__ = "0.1.1"
|
||||
|
||||
+28
-7
@@ -42,6 +42,7 @@ class API:
|
||||
openapi=None,
|
||||
openapi_route="/schema.yml",
|
||||
static_dir="static",
|
||||
static_route="/static",
|
||||
templates_dir="templates",
|
||||
enable_hsts=False,
|
||||
):
|
||||
@@ -49,7 +50,7 @@ class API:
|
||||
self.version = version
|
||||
self.openapi_version = openapi
|
||||
self.static_dir = Path(os.path.abspath(static_dir))
|
||||
self.static_route = f"/{static_dir}"
|
||||
self.static_route = static_route
|
||||
self.templates_dir = Path(os.path.abspath(templates_dir))
|
||||
self.built_in_templates_dir = Path(
|
||||
os.path.abspath(os.path.dirname(__file__) + "/templates")
|
||||
@@ -74,6 +75,8 @@ class API:
|
||||
if self.openapi_version:
|
||||
self.add_route(openapi_route, self.schema_response)
|
||||
|
||||
self.default_endpoint = None
|
||||
|
||||
@property
|
||||
def _apispec(self):
|
||||
spec = APISpec(
|
||||
@@ -199,7 +202,7 @@ class API:
|
||||
# Run on_request first.
|
||||
try:
|
||||
r = getattr(view, "on_request")(req, resp)
|
||||
if hasattr(r, 'send'):
|
||||
if hasattr(r, "send"):
|
||||
await r
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -209,7 +212,7 @@ class API:
|
||||
|
||||
try:
|
||||
r = getattr(view, f"on_{method}")(req, resp)
|
||||
if hasattr(r, 'send'):
|
||||
if hasattr(r, "send"):
|
||||
await r
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -218,15 +221,24 @@ class API:
|
||||
|
||||
return resp
|
||||
|
||||
def add_route(self, route, endpoint, *, check_existing=True):
|
||||
def add_route(self, route, endpoint=None, *, default=False, static=False, check_existing=True):
|
||||
"""Add a route to the API.
|
||||
|
||||
:param route: A string representation of the route.
|
||||
:param endpoint: The endpoint for the route -- can be a callable, a class, a WSGI application, or graphene schema (GraphQL).
|
||||
:param endpoint: The endpoint for the route -- can be a callable, a class, or graphene schema (GraphQL).
|
||||
:param default: If ``True``, all unknown requests will route to this view.
|
||||
:param static: If ``True``, and no endpoint was passed, render "static/index.html", and it will become a default route.
|
||||
:param check_existing: If ``True``, an AssertionError will be raised, if the route is already defined.
|
||||
"""
|
||||
if check_existing:
|
||||
assert route not in self.routes
|
||||
|
||||
if not endpoint and static:
|
||||
endpoint = self.static_response
|
||||
default = True
|
||||
|
||||
if default:
|
||||
self.default_endpoint = endpoint
|
||||
self.routes[route] = Route(route, endpoint)
|
||||
# TODO: A better datastructer or sort it once the app is loaded
|
||||
self.routes = dict(
|
||||
@@ -234,8 +246,17 @@ class API:
|
||||
)
|
||||
|
||||
def default_response(self, req, resp):
|
||||
resp.status_code = status_codes.HTTP_404
|
||||
resp.text = "Not found."
|
||||
if self.default_endpoint:
|
||||
self.default_endpoint(req, resp)
|
||||
else:
|
||||
resp.status_code = status_codes.HTTP_404
|
||||
resp.text = "Not found."
|
||||
|
||||
def static_response(self, req, resp):
|
||||
index = (self.static_dir / "index.html").resolve()
|
||||
if os.path.exists(index):
|
||||
with open(index, "r") as f:
|
||||
resp.text = f.read()
|
||||
|
||||
def schema_response(self, req, resp):
|
||||
resp.status_code = status_codes.HTTP_200
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
lorem
|
||||
Reference in New Issue
Block a user