Пример #1
0
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
Пример #2
0
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