Compare commits

...

16 Commits

Author SHA1 Message Date
kennethreitz cee5ca8873 v0.1.1 2018-10-17 06:01:41 -07:00
kennethreitz d961d4ab43 default routes 2018-10-17 06:01:27 -07:00
kennethreitz 5205150a89 default route 2018-10-17 05:53:23 -07:00
kennethreitz 48e58cde5d docker 2018-10-17 05:19:22 -07:00
kennethreitz 033e91f8df name 2018-10-17 05:15:25 -07:00
kennethreitz aab3705897 myapi 2018-10-17 05:14:19 -07:00
kennethreitz d02efa81f2 deployment 2018-10-17 05:12:11 -07:00
kennethreitz 95a8240da7 single-page webapps 2018-10-17 04:58:11 -07:00
kennethreitz dd0ddab610 single page 2018-10-17 04:52:02 -07:00
kennethreitz d23ac10f90 version 2018-10-17 04:49:00 -07:00
kennethreitz ec18290b8a changelog 2018-10-17 04:48:38 -07:00
kennethreitz 2c4cd39dc9 static application support 2018-10-17 04:48:33 -07:00
kennethreitz 830bad0b85 docs for #53 2018-10-17 04:47:39 -07:00
kennethreitz f14ef6fa15 #53 2018-10-17 04:45:12 -07:00
kennethreitz 7400b1c83d static support #53 2018-10-17 04:38:51 -07:00
kennethreitz e7caf39fba static_route 2018-10-17 04:25:09 -07:00
8 changed files with 107 additions and 8 deletions
+9
View File
@@ -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.
+57
View File
@@ -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
+2
View File
@@ -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
+9
View File
@@ -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
View File
@@ -1 +1 @@
__version__ = "0.0.10"
__version__ = "0.1.1"
+28 -7
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
lorem
View File