Changed tweets, added eca
This commit is contained in:
135
eca/http.py
Normal file
135
eca/http.py
Normal file
@@ -0,0 +1,135 @@
|
||||
import http.cookies
|
||||
import logging
|
||||
import json
|
||||
import collections
|
||||
from . import httpd
|
||||
from . import sse
|
||||
from . import fire, get_context
|
||||
from . import sessions
|
||||
|
||||
|
||||
# Logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# bring some external handlers into this module's scope
|
||||
# (now you can just import eca.http and have access to all standard handlers)
|
||||
StaticContent = httpd.StaticContent
|
||||
SessionManager = sessions.SessionManager
|
||||
|
||||
|
||||
class Cookies(httpd.Filter):
|
||||
"""Filter to read cookies from request."""
|
||||
def handle(self):
|
||||
# process available cookies
|
||||
cookies = http.cookies.SimpleCookie()
|
||||
if 'cookie' in self.request.headers:
|
||||
cookies.load(self.request.headers['cookie'])
|
||||
|
||||
# set cookies on request
|
||||
self.request.cookies = cookies
|
||||
|
||||
|
||||
|
||||
class HelloWorld(httpd.Handler):
|
||||
"""The mandatory Hello World example."""
|
||||
def handle_GET(self):
|
||||
self.request.send_response(200)
|
||||
self.request.send_header('content-type','text/html; charset=utf-8')
|
||||
self.request.end_headers()
|
||||
|
||||
output = "<!DOCTYPE html><html><body><h1>Hello world!</h1><p><i>eca-session:</i> {}</p></body></html>"
|
||||
|
||||
try:
|
||||
if not hasattr(self.request, 'cookies'): raise KeyError()
|
||||
cookie = self.request.cookies['eca-session'].value
|
||||
except KeyError:
|
||||
cookie = '<i>no cookie</i>';
|
||||
|
||||
self.request.wfile.write(output.format(cookie).encode('utf-8'))
|
||||
|
||||
|
||||
def Redirect(realpath):
|
||||
"""
|
||||
Factory for redirection handlers.
|
||||
"""
|
||||
class RedirectHandler(httpd.Handler):
|
||||
def handle_GET(self):
|
||||
location = None
|
||||
|
||||
# check for absolute paths
|
||||
if realpath.startswith("http://") or realpath.startswith('https://'):
|
||||
location = realpath
|
||||
else:
|
||||
host = self.request.server.server_address[0]
|
||||
if self.request.server.server_address[1] != 80:
|
||||
host += ":{}".format(self.request.server.server_address[1])
|
||||
|
||||
if 'host' in self.request.headers:
|
||||
host = self.request.headers['host']
|
||||
|
||||
location = "http://{}{}".format(host, realpath)
|
||||
|
||||
self.request.send_response(302)
|
||||
self.request.send_header('content-type','text/html; charset=utf-8')
|
||||
self.request.send_header('location',location)
|
||||
self.request.end_headers()
|
||||
output = "<!DOCTYPE html><html><body><p>Redirect to <a href='{0}'>{0}</a></p></body></html>"
|
||||
self.request.wfile.write(output.format(location).encode('utf-8'))
|
||||
|
||||
return RedirectHandler
|
||||
|
||||
|
||||
def GenerateEvent(name):
|
||||
"""
|
||||
This function returns a handler class that creates the named event based
|
||||
on the posted JSON data.
|
||||
"""
|
||||
class EventGenerationHandler(httpd.Handler):
|
||||
def handle_POST(self):
|
||||
# handle weirdness
|
||||
if 'content-length' not in self.request.headers:
|
||||
self.request.send_error(411)
|
||||
return
|
||||
|
||||
# read content-length header
|
||||
length = int(self.request.headers['content-length'])
|
||||
|
||||
# grab data
|
||||
data = self.request.rfile.read(length)
|
||||
try:
|
||||
structured = json.loads(data.decode('utf-8'))
|
||||
except ValueError as e:
|
||||
self.request.send_error(400, "Bad request: "+str(e))
|
||||
return
|
||||
|
||||
if not isinstance(structured, collections.abc.Mapping):
|
||||
self.request.send_error(400, "Bad request: expect a JSON object")
|
||||
return
|
||||
|
||||
try:
|
||||
fire(name, structured)
|
||||
except NotImplementedError:
|
||||
logger.warn("Event generated by HTTP request without active session. Do you have a SessionManager configured?")
|
||||
self.request.send_error(500, "No current context available.")
|
||||
return
|
||||
|
||||
self.request.send_response(202)
|
||||
self.request.send_header('content-type', 'text/plain; charset=utf-8')
|
||||
self.request.send_header('content-length', 0)
|
||||
self.request.end_headers()
|
||||
|
||||
return EventGenerationHandler
|
||||
|
||||
|
||||
class EventStream(sse.ServerSideEvents):
|
||||
def go_subscribe(self):
|
||||
def receiver(name, event):
|
||||
self.send_event(event.data.get('json'), event.name, event.data.get('id'))
|
||||
|
||||
self.receiver = receiver
|
||||
context = get_context()
|
||||
context.channel.subscribe(self.receiver, 'emit')
|
||||
|
||||
def go_unsubscribe(self):
|
||||
context = get_context()
|
||||
context.channel.unsubscribe(self.receiver, 'emit')
|
||||
Reference in New Issue
Block a user