kopia lustrzana https://github.com/cirospaciari/socketify.py
add Template support with mako and jinja2 examples
rodzic
0b2908446c
commit
84d849172d
|
@ -30,6 +30,7 @@
|
||||||
- Automatic Ping / Pong Support
|
- Automatic Ping / Pong Support
|
||||||
- Per Socket Data
|
- Per Socket Data
|
||||||
- Middlewares
|
- Middlewares
|
||||||
|
- Templates Support (examples with [Mako](https://github.com/cirospaciari/socketify.py/tree/main/examples/template_mako.py) and [Jinja2)](https://github.com/cirospaciari/socketify.py/tree/main/examples/template_jinja2.py))
|
||||||
## :mag_right: Upcoming Features
|
## :mag_right: Upcoming Features
|
||||||
- Fetch like API powered by libuv
|
- Fetch like API powered by libuv
|
||||||
- Async file IO powered by libuv
|
- Async file IO powered by libuv
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#Simple example of mako and jinja2 template plugin for socketify.py
|
||||||
|
from mako.template import Template
|
||||||
|
from mako.lookup import TemplateLookup
|
||||||
|
from mako import exceptions
|
||||||
|
|
||||||
|
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|
||||||
|
class Jinja2Template:
|
||||||
|
def __init__(self, searchpath, encoding='utf-8', followlinks=False):
|
||||||
|
self.env = Environment(loader=FileSystemLoader(searchpath, encoding, followlinks))
|
||||||
|
|
||||||
|
#You can also add caching and logging strategy here if you want ;)
|
||||||
|
def render(self, templatename, **kwargs):
|
||||||
|
try:
|
||||||
|
template = self.env.get_template(templatename)
|
||||||
|
return template.render(**kwargs)
|
||||||
|
except Exception as err:
|
||||||
|
return str(err)
|
||||||
|
|
||||||
|
class MakoTemplate:
|
||||||
|
def __init__(self, **options):
|
||||||
|
self.lookup = TemplateLookup(**options)
|
||||||
|
|
||||||
|
#You can also add caching and logging strategy here if you want ;)
|
||||||
|
def render(self, templatename, **kwargs):
|
||||||
|
try:
|
||||||
|
template = self.lookup.get_template(templatename)
|
||||||
|
return template.render(**kwargs)
|
||||||
|
except Exception as err:
|
||||||
|
return exceptions.html_error_template().render()
|
|
@ -3,4 +3,5 @@ aiofiles
|
||||||
aiofile
|
aiofile
|
||||||
redis
|
redis
|
||||||
strawberry-graphql
|
strawberry-graphql
|
||||||
|
mako
|
||||||
git+https://github.com/cirospaciari/socketify.py.git@main#socketify --global-option="build_ext"
|
git+https://github.com/cirospaciari/socketify.py.git@main#socketify --global-option="build_ext"
|
|
@ -0,0 +1,14 @@
|
||||||
|
from socketify import App
|
||||||
|
#see helper/templates.py for plugin implementation
|
||||||
|
from helpers.templates import Jinja2Template
|
||||||
|
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
app.template(Jinja2Template("./templates", encoding='utf-8', followlinks=False))
|
||||||
|
|
||||||
|
async def home(res, req):
|
||||||
|
res.render("jinja2_home.html", title="Hello", message="Hello, World")
|
||||||
|
|
||||||
|
app.get("/", home)
|
||||||
|
app.listen(3000, lambda config: print("Listening on port http://localhost:%s now\n" % str(config.port)))
|
||||||
|
app.run()
|
|
@ -0,0 +1,14 @@
|
||||||
|
from socketify import App
|
||||||
|
#see helper/templates.py for plugin implementation
|
||||||
|
from helpers.templates import MakoTemplate
|
||||||
|
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
app.template(MakoTemplate(directories=['./templates'], output_encoding='utf-8', encoding_errors='replace'))
|
||||||
|
|
||||||
|
async def home(res, req):
|
||||||
|
res.render("mako_home.html", message="Hello, World")
|
||||||
|
|
||||||
|
app.get("/", home)
|
||||||
|
app.listen(3000, lambda config: print("Listening on port http://localhost:%s now\n" % str(config.port)))
|
||||||
|
app.run()
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html
|
||||||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||||
|
<head>
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="header">
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{%- block body %}{%- endblock %}
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,4 @@
|
||||||
|
{% extends "jinja2_base.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<p>this is the body content. {{ message }}</p>
|
||||||
|
{% endblock body %}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div class="header">
|
||||||
|
<%block name="header"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
${self.body()}
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<%block name="footer">
|
||||||
|
this is the footer
|
||||||
|
</%block>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<%inherit file="mako_base.html"/>
|
||||||
|
|
||||||
|
<%block name="header">
|
||||||
|
this is some header content
|
||||||
|
</%block>
|
||||||
|
|
||||||
|
this is the body content. ${ message }
|
|
@ -422,7 +422,7 @@ def uws_websocket_upgrade_handler(res, req, context, user_data):
|
||||||
if not user_data == ffi.NULL:
|
if not user_data == ffi.NULL:
|
||||||
try:
|
try:
|
||||||
(handlers, app) = ffi.from_handle(user_data)
|
(handlers, app) = ffi.from_handle(user_data)
|
||||||
response = AppResponse(res, app.loop, app.SSL)
|
response = AppResponse(res, app.loop, app.SSL, app._template)
|
||||||
request = AppRequest(req)
|
request = AppRequest(req)
|
||||||
handler = handlers.upgrade
|
handler = handlers.upgrade
|
||||||
if inspect.iscoroutinefunction(handler):
|
if inspect.iscoroutinefunction(handler):
|
||||||
|
@ -463,7 +463,7 @@ def uws_generic_method_handler(res, req, user_data):
|
||||||
if not user_data == ffi.NULL:
|
if not user_data == ffi.NULL:
|
||||||
try:
|
try:
|
||||||
(handler, app) = ffi.from_handle(user_data)
|
(handler, app) = ffi.from_handle(user_data)
|
||||||
response = AppResponse(res, app.loop, app.SSL)
|
response = AppResponse(res, app.loop, app.SSL, app._template)
|
||||||
request = AppRequest(req)
|
request = AppRequest(req)
|
||||||
if inspect.iscoroutinefunction(handler):
|
if inspect.iscoroutinefunction(handler):
|
||||||
response.grab_aborted_handler()
|
response.grab_aborted_handler()
|
||||||
|
@ -1044,7 +1044,7 @@ class AppRequest:
|
||||||
self._ptr = ffi.NULL
|
self._ptr = ffi.NULL
|
||||||
|
|
||||||
class AppResponse:
|
class AppResponse:
|
||||||
def __init__(self, response, loop, ssl):
|
def __init__(self, response, loop, ssl, render=None):
|
||||||
self.res = response
|
self.res = response
|
||||||
self.SSL = ssl
|
self.SSL = ssl
|
||||||
self.aborted = False
|
self.aborted = False
|
||||||
|
@ -1060,6 +1060,7 @@ class AppResponse:
|
||||||
self._chunkFuture = None
|
self._chunkFuture = None
|
||||||
self._dataFuture = None
|
self._dataFuture = None
|
||||||
self._data = None
|
self._data = None
|
||||||
|
self._render = render
|
||||||
|
|
||||||
def cork(self, callback):
|
def cork(self, callback):
|
||||||
if not self.aborted:
|
if not self.aborted:
|
||||||
|
@ -1253,6 +1254,12 @@ class AppResponse:
|
||||||
self.cork(lambda res: res.end(message, end_connection))
|
self.cork(lambda res: res.end(message, end_connection))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def render(self, *args, **kwargs):
|
||||||
|
if self._render:
|
||||||
|
self.cork_end(self._render.render(*args, **kwargs))
|
||||||
|
return self
|
||||||
|
raise RuntimeError("No registered templated engine")
|
||||||
|
|
||||||
def get_remote_address_bytes(self):
|
def get_remote_address_bytes(self):
|
||||||
buffer = ffi.new("char**")
|
buffer = ffi.new("char**")
|
||||||
length = lib.uws_res_get_remote_address(self.SSL, self.res, buffer)
|
length = lib.uws_res_get_remote_address(self.SSL, self.res, buffer)
|
||||||
|
@ -1467,6 +1474,7 @@ class App:
|
||||||
socket_options_ptr = ffi.new("struct us_socket_context_options_t *")
|
socket_options_ptr = ffi.new("struct us_socket_context_options_t *")
|
||||||
socket_options = socket_options_ptr[0]
|
socket_options = socket_options_ptr[0]
|
||||||
self.options = options
|
self.options = options
|
||||||
|
self._template = None
|
||||||
if options != None:
|
if options != None:
|
||||||
self.is_ssl = True
|
self.is_ssl = True
|
||||||
self.SSL = ffi.cast("int", 1)
|
self.SSL = ffi.cast("int", 1)
|
||||||
|
@ -1498,6 +1506,8 @@ class App:
|
||||||
self._missing_server_handler = None
|
self._missing_server_handler = None
|
||||||
|
|
||||||
|
|
||||||
|
def template(self, template_engine):
|
||||||
|
self._template = template_engine
|
||||||
|
|
||||||
def static(self, route, directory):
|
def static(self, route, directory):
|
||||||
static_route(self, route, directory)
|
static_route(self, route, directory)
|
||||||
|
|
Ładowanie…
Reference in New Issue