tav (owner)

Revisions

gist: 228808 Download_button fork
public
Public Clone URL: git://gist.github.com/228808.git
Embed All Files: show embed
evhttp.py #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import os
import signal
import socket
import sys
 
from errno import EAGAIN, EWOULDBLOCK
 
import pyev
 
# ------------------------------------------------------------------------------
# some konstants
# ------------------------------------------------------------------------------
 
RETRY_STATES = tuple(set([EAGAIN, EWOULDBLOCK])) # EINTR
 
HELLO_WORLD = '\r\n'.join([
    'HTTP/1.1 200 OK', 'Connection: close', 'Content-type: text/html',
    'Server: MicroHTTPServer/0.1', 'Content-Length: 11', '', 'Hello World'
    ])
 
class HTTPConnection(object):
 
    def __init__(self, connection, address, server):
        self.connection = connection
        self.address = address
        self.server = server
        self._buffer = ''
        connection.setblocking(0)
        self._event = pyev.Io(self.connection.fileno(), pyev.EV_READ, LOOP, self.do_read)
        self._event.start()
 
    def do_read(self, watcher, events):
        print "Reading"
        self._buffer += self.connection.recv(1024)
        if '\r\n\r\n' in self._buffer:
            self._event.stop()
            self.hello()
 
    def hello(self):
        wfile = self.connection.makefile('wb', 0)
        wfile.write(HELLO_WORLD)
        wfile.flush()
        wfile.close()
        self.connection.close()
 
# ------------------------------------------------------------------------------
# our kore server
# ------------------------------------------------------------------------------
 
class MicroHTTPServer(object):
    """Micro HTTP Server."""
 
    _socket = None
    _shutdown = False
 
    def __init__(self, handler=HTTPConnection):
        self.handler = handler
 
    def listen(self, host='', port=9090, backlog=1024):
        """Start listening on the given ``host`` and ``port``."""
 
        assert not self._socket, "This server is already listening."
 
        self.host, self.port = host, port
        self._socket = sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
        sock.setblocking(0)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind((host, port))
 
        if sys.platform == 'darwin':
            backlog = min(backlog, 128)
        elif os.name == 'nt':
            backlog = min(backlog, 5)
 
        sock.listen(backlog)
        socket_descriptor = sock.fileno()
 
        self.register(socket_descriptor)
 
# flags = fcntl.fcntl(self._socket.fileno(), fcntl.F_GETFD)
# flags |= fcntl.FD_CLOEXEC
# fcntl.fcntl(self._socket.fileno(), fcntl.F_SETFD, flags)
 
    def register(self, socket_descriptor):
        ev = pyev.Io(socket_descriptor, pyev.EV_READ, LOOP, self.handle_connection)
        print ev.start()
        print "Started server"
 
    def handle_connection(self, watcher, events):
        try:
            connection, address = self._socket.accept()
        except socket.error, reason:
            if reason[0] in RETRY_STATES:
                return
            raise
        self.handler(connection, address, self)
 
if 1:
    LOOP = pyev.default_loop()
    # LOOP = pyev.Loop(pyev.EVBACKEND_SELECT)
elif 'linux' in sys.platform:
    LOOP = pyev.Loop(pyev.EVBACKEND_EPOLL)
elif sys.platform == 'darwin':
    LOOP = pyev.Loop(pyev.EVBACKEND_KQUEUE)
 
def sig_cb(watcher, events):
    print("got SIGINT")
    # optional - stop all watchers
    if watcher.data:
        print("stopping watchers: {0}".format(watcher.data))
        for w in watcher.data:
            w.stop()
    # unloop all nested loop
    print("stopping the loop: {0}".format(watcher.loop))
    watcher.loop.unloop()
 
sig = pyev.Signal(signal.SIGINT, LOOP, sig_cb)
sig.start()
    
def start():
    s = MicroHTTPServer()
    s.listen()
    LOOP.loop()
 
# ------------------------------------------------------------------------------
# test
# ------------------------------------------------------------------------------
 
start()