def yyyy(user_data_id, unset_event=False): ud_id = ctypes.cast(user_data_id, ctypes.POINTER(ctypes.c_long)) #print "DEL %i (%r)" % (ud_id.contents.value, ud_map.keys() ) if not ud_id: return None, None user_data = ud_map[ud_id.contents.value] # use the same environ #return user_data['callback'](*user_data['args'], **user_data['kwargs']) environ = user_data['response'].environ environ['PATH_INFO'] = user_data['callback_url'] environ['response_prev'] = user_data['response'] del ud_map[ud_id.contents.value] if unset_event: libevent.event_del(user_data['byref(event)']) if 'buf' in environ and environ['buf']: libevent.evbuffer_free(environ['buf']) del environ['buf'] del user_data['byref(event)'] del user_data['byref(id)'] del user_data['id'] del user_data['event'] return user_data, environ
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