def defer_for_fifo_handler(fd, nr, user_data_id): user_data, environ = yyyy(user_data_id) environ['event_flags'] = nr libevent.evhttp_connection_set_closecb(ctypes.cast(user_data['response'].http_request, req_type).contents.evcon, close_callback_ptr, None) req = ctypes.cast(user_data['response'].http_request, req_type) try: os.read( user_data['fd'], 4096) # if read was correct, than repeat the event request. # you're going to receive yet new event with socket closed. #user_data, event = xxxx(user_data['response'], user_data['callback_url'], user_data['fd']) #libevent.event_set(user_data['byref(event)'], user_data['fd'], libevent.EV_READ, defer_for_fifo_hanlder_ptr, user_data['byref(id)']) #libevent.evtimer_add(user_data['byref(event)'], None) #return 1 except OSError: # f**k the result pass os.close( user_data['fd'] ) user_data['fd'] = 0 root_handler(user_data['response'].http_request, environ ) del user_data return 1
def root_handler(req, environ, event_type=0): t0 = time.time() # force type conversion. I have no idea why it's needed but it is. req = ctypes.cast(req, req_type) if not environ: environ = request_to_environ(req) first_request = True else: first_request = False environ['event_type'] = event_type try: status_code, status_reason, response_headers, data, response = django_handler( environ.copy() ) except Exception: # all exceptions... traceback.print_exc(file=sys.stdout) status_code, status_reason, response_headers, data, response = \ 500 , 'INTERNAL SERVER ERROR', (), '<h1>500 internal server error</h1>', object() if hasattr(response, 'continuation') and response.continuation: continuation = True else: continuation = False if first_request: # only on first request for key, value in response_headers: libevent.evhttp_add_header(req.contents.output_headers, str(key), str(value)) content_length = 0 content_type = '' # first_request, and we don't continue and string -> straight response if event_type == EVENT_CLOSED: if data: print "fuckoff, event is closed and you want to return data" elif first_request and isinstance(data, str) and not continuation: # libevent is broken, it's not sending content-length for http1.0 libevent.evhttp_add_header(req.contents.output_headers, 'Content-Length', str(len(data))) assert(first_request) assert(isinstance(data, str)) buf=libevent.evbuffer_new() libevent.evbuffer_add(buf, data, len(data)) libevent.evhttp_send_reply(req, status_code, status_reason, buf) libevent.evbuffer_free(buf) content_length = len(data) content_type = '' # else: chunked: else: #force chunked if isinstance(data, str): # yep, we need list data = [data] assert(isinstance(data, list)) # first reqiest: open the chunkinkg mode if first_request: buf=libevent.evbuffer_new() libevent.evhttp_send_reply_start(req, status_code, status_reason) else: buf = environ['buf'] buf = ctypes.cast(buf, buf_type) content_type = 'chunk' # for chunk in chunks... for data_chunk in data: if not data: continue assert(isinstance(data_chunk, str)) libevent.evbuffer_add(buf,data_chunk, len(data_chunk)) libevent.evhttp_send_reply_chunk(req, buf) content_length += len(data_chunk) # don't continue the answer in the future -> close if not continuation: libevent.evhttp_send_reply_end(req) libevent.evbuffer_free(buf) if 'buf' in environ: del environ['buf'] else: # don't close the connection and save the request object and environ response.environ = environ response.http_request = req environ['buf'] = buf if getattr(response, 'schedule', None) and response.schedule and event_type != EVENT_CLOSED: libevent.evhttp_connection_set_closecb(req.contents.evcon, close_callback_ptr, response.schedule) response.schedule = None t1 = time.time() print '''%(date)s %(host)s "%(method)s %(url)s %(http)s" %(status_code)i %(content_length)i %(content_type)s %(continuation)s (%(time).3fms)''' % { 'date':datetime.datetime.now().strftime("[%Y-%m-%d %H:%M:%S]"), 'method':environ['REQUEST_METHOD'], 'url': environ['PATH_INFO'] + '?' + environ['QUERY_STRING'], 'http': environ['SERVER_PROTOCOL'], 'status_code': status_code, 'content_length': content_length, 'content_type': content_type, 'continuation': '...<' if event_type==EVENT_CLOSED else '' if not continuation else '>...' if first_request else '...', 'host': '%s:%i' % (environ['REMOTE_HOST'], environ['REMOTE_PORT']), 'time': (t1-t0) * 1000, # in miliseconds } return 1