<s> import urlparse <EOL> import collections <EOL> import re <EOL> import urllib2 <EOL> import time <EOL> import logging <EOL> import base64 <EOL> import Cookie <EOL> from functools import wraps <EOL> from monocle import _o , Return <EOL> from monocle . stack . network import ConnectionLost , Client , SSLClient <EOL> log = logging . getLogger ( __name__ ) <EOL> class _NotSetFlag ( object ) : <EOL> pass <EOL> class HttpHeaders ( collections . MutableMapping ) : <EOL> def __init__ ( self , headers = None ) : <EOL> self . headers = [ ] <EOL> self . keyset = set ( ) <EOL> if hasattr ( headers , '<STR_LIT>' ) : <EOL> for k , v in headers . iteritems ( ) : <EOL> self . add ( k , v ) <EOL> else : <EOL> for k , v in headers or [ ] : <EOL> self . add ( k , v ) <EOL> def __len__ ( self ) : <EOL> return len ( self . headers ) <EOL> def keys ( self ) : <EOL> return [ k for k , v in self . headers ] <EOL> def add ( self , key , value ) : <EOL> key = key . lower ( ) <EOL> self . keyset . add ( key ) <EOL> self . headers . append ( ( key , value ) ) <EOL> def items ( self ) : <EOL> return self . headers <EOL> def __iter__ ( self ) : <EOL> return ( k for k , v in self . headers ) <EOL> def iteritems ( self ) : <EOL> return ( x for x in self . headers ) <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . __class__ . __name__ , repr ( self . headers ) ) <EOL> def get_list ( self , key , default = _NotSetFlag ) : <EOL> key = key . lower ( ) <EOL> if key not in self . keyset : <EOL> if default == _NotSetFlag : <EOL> raise KeyError ( key ) <EOL> else : <EOL> return default <EOL> vals = [ v for k , v in self . headers if k == key ] <EOL> return vals <EOL> def __getitem__ ( self , key ) : <EOL> vals = self . get_list ( key ) <EOL> if len ( vals ) == <NUM_LIT:1> : <EOL> return vals [ <NUM_LIT:0> ] <EOL> else : <EOL> return vals <EOL> def __setitem__ ( self , key , value ) : <EOL> try : <EOL> del self [ key ] <EOL> except KeyError : <EOL> pass <EOL> return self . add ( key , value ) <EOL> def __delitem__ ( self , key ) : <EOL> key = key . lower ( ) <EOL> if key not in self . keyset : <EOL> raise KeyError ( key ) <EOL> self . keyset . remove ( key ) <EOL> self . headers = [ ( k , v ) for k , v in self . headers if k != key ] <EOL> class HttpRequest ( object ) : <EOL> def __init__ ( self , proto = '<STR_LIT>' , host = None , method = None , <EOL> uri = None , args = None , remote_ip = None , headers = None , <EOL> body = None , body_file = None ) : <EOL> self . proto = proto <EOL> self . host = host <EOL> self . method = method <EOL> self . uri = uri <EOL> self . remote_ip = remote_ip <EOL> self . headers = headers <EOL> self . body = body <EOL> self . body_file = body_file <EOL> self . path , _ , self . query = uri . partition ( '<STR_LIT:?>' ) <EOL> self . query_args = urlparse . parse_qs ( self . query , keep_blank_values = True ) <EOL> self . args = args <EOL> self . cookies = { } <EOL> for cookie in self . headers . get_list ( "<STR_LIT>" , [ ] ) : <EOL> try : <EOL> for name , morsel in Cookie . BaseCookie ( cookie ) . iteritems ( ) : <EOL> self . cookies [ name ] = morsel . value <EOL> except Cookie . CookieError : <EOL> pass <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( <EOL> self . __class__ . __name__ , self . method , self . path , self . proto , self . headers ) <EOL> def get_basic_auth ( self ) : <EOL> if '<STR_LIT>' not in self . headers : <EOL> return None , None <EOL> auth = self . headers [ "<STR_LIT>" ] <EOL> try : <EOL> method , b64 = auth . split ( "<STR_LIT:U+0020>" ) <EOL> if method . lower ( ) != "<STR_LIT>" : <EOL> return None , None <EOL> username , password = base64 . decodestring ( b64 ) . split ( '<STR_LIT::>' , <NUM_LIT:1> ) <EOL> except Exception : <EOL> return None , None <EOL> return username , password <EOL> class HttpResponse ( object ) : <EOL> def __init__ ( self , code , msg = None , headers = None , body = None , proto = None ) : <EOL> self . code = code <EOL> self . msg = msg <EOL> self . headers = headers or HttpHeaders ( ) <EOL> self . body = body <EOL> self . proto = proto or '<STR_LIT>' <EOL> def parse_headers ( lines ) : <EOL> headers = HttpHeaders ( ) <EOL> for line in lines : <EOL> k , v = line . split ( "<STR_LIT::>" , <NUM_LIT:1> ) <EOL> headers . add ( k , v . lstrip ( ) ) <EOL> return headers <EOL> def parse_request ( data ) : <EOL> data = data [ : - <NUM_LIT:4> ] <EOL> lines = data . split ( "<STR_LIT:\r\n>" ) <EOL> method , path , proto = lines [ <NUM_LIT:0> ] . split ( "<STR_LIT:U+0020>" , <NUM_LIT:2> ) <EOL> headers = parse_headers ( lines [ <NUM_LIT:1> : ] ) <EOL> return method , path , proto , headers <EOL> def parse_response ( data ) : <EOL> data = data [ : - <NUM_LIT:4> ] <EOL> lines = data . split ( "<STR_LIT:\r\n>" ) <EOL> parts = lines [ <NUM_LIT:0> ] . split ( "<STR_LIT:U+0020>" ) <EOL> proto = parts [ <NUM_LIT:0> ] <EOL> code = parts [ <NUM_LIT:1> ] <EOL> if len ( parts ) > <NUM_LIT:2> : <EOL> msg = parts [ <NUM_LIT:2> ] <EOL> else : <EOL> msg = "<STR_LIT>" <EOL> headers = parse_headers ( lines [ <NUM_LIT:1> : ] ) <EOL> return proto , code , msg , headers <EOL> @ _o <EOL> def read_request ( conn ) : <EOL> data = yield conn . read_until ( "<STR_LIT>" ) <EOL> method , path , proto , headers = parse_request ( data ) <EOL> body = None <EOL> if method in [ "<STR_LIT:POST>" , "<STR_LIT>" ] and "<STR_LIT>" in headers : <EOL> cl = int ( headers [ "<STR_LIT>" ] ) <EOL> body = yield conn . read ( cl ) <EOL> yield Return ( method , path , proto , headers , body ) <EOL> @ _o <EOL> def write_request ( conn , method , path , headers , body = None ) : <EOL> yield conn . write ( "<STR_LIT>" % ( method , path ) ) <EOL> for k , v in headers . iteritems ( ) : <EOL> yield conn . write ( "<STR_LIT>" % ( k , v ) ) <EOL> yield conn . write ( "<STR_LIT:\r\n>" ) <EOL> if body : <EOL> yield conn . write ( body ) <EOL> @ _o <EOL> def read_response ( conn ) : <EOL> data = yield conn . read_until ( "<STR_LIT>" ) <EOL> proto , code , msg , headers = parse_response ( data ) <EOL> proto = proto . lower ( ) <EOL> content_length = int ( headers . get ( '<STR_LIT>' , <NUM_LIT:0> ) ) <EOL> body = "<STR_LIT>" <EOL> if headers . get ( '<STR_LIT>' , '<STR_LIT>' ) . lower ( ) == '<STR_LIT>' : <EOL> while True : <EOL> line = yield conn . read_until ( "<STR_LIT:\r\n>" ) <EOL> line = line [ : - <NUM_LIT:2> ] <EOL> parts = line . split ( '<STR_LIT:;>' ) <EOL> chunk_len = int ( parts [ <NUM_LIT:0> ] , <NUM_LIT:16> ) <EOL> body += yield conn . read ( chunk_len ) <EOL> yield conn . read_until ( "<STR_LIT:\r\n>" ) <EOL> if not chunk_len : <EOL> break <EOL> elif content_length : <EOL> body = yield conn . read ( content_length ) <EOL> elif ( ( proto == '<STR_LIT>' and <EOL> not headers . get ( '<STR_LIT>' , '<STR_LIT>' ) . lower ( ) == '<STR_LIT>' ) or <EOL> ( proto == '<STR_LIT>' and <EOL> headers . get ( '<STR_LIT>' , '<STR_LIT>' ) . lower ( ) == '<STR_LIT>' ) ) : <EOL> while True : <EOL> try : <EOL> body += yield conn . read_some ( ) <EOL> except ConnectionLost : <EOL> break <EOL> yield Return ( HttpResponse ( code , msg , headers , body , proto ) ) <EOL> @ _o <EOL> def write_response ( conn , resp ) : <EOL> yield conn . write ( "<STR_LIT>" % ( resp . proto . upper ( ) , resp . code , resp . msg ) ) <EOL> for k , v in resp . headers . iteritems ( ) : <EOL> yield conn . write ( "<STR_LIT>" % ( k , v ) ) <EOL> yield conn . write ( '<STR_LIT:\r\n>' ) <EOL> if resp . body : <EOL> yield conn . write ( resp . body ) <EOL> class HttpClient ( object ) : <EOL> DEFAULT_PORTS = { '<STR_LIT:http>' : <NUM_LIT> , <EOL> '<STR_LIT>' : <NUM_LIT> } <EOL> def __init__ ( self ) : <EOL> self . client = None <EOL> self . scheme = None <EOL> self . host = None <EOL> self . port = None <EOL> self . _timeout = None <EOL> @ property <EOL> def timeout ( self ) : <EOL> return self . _timeout <EOL> @ timeout . setter <EOL> def timeout ( self , value ) : <EOL> self . _timeout = value <EOL> if self . client : <EOL> self . client . timeout = value <EOL> @ _o <EOL> def connect ( self , host , port , scheme = '<STR_LIT:http>' , timeout = None ) : <EOL> if timeout is not None : <EOL> self . timeout = None <EOL> if self . client and not self . client . is_closed ( ) : <EOL> self . client . close ( ) <EOL> if scheme == '<STR_LIT:http>' : <EOL> self . client = Client ( ) <EOL> elif scheme == '<STR_LIT>' : <EOL> self . client = SSLClient ( ) <EOL> else : <EOL> raise HttpException ( '<STR_LIT>' % scheme ) <EOL> self . scheme = scheme <EOL> self . host = host <EOL> self . port = port <EOL> self . client . timeout = self . _timeout <EOL> yield self . client . connect ( self . host , self . port ) <EOL> @ _o <EOL> def request ( self , url , headers = None , method = '<STR_LIT:GET>' , body = None ) : <EOL> parts = urlparse . urlsplit ( url ) <EOL> scheme = parts . scheme or self . scheme <EOL> if scheme not in [ '<STR_LIT:http>' , '<STR_LIT>' ] : <EOL> raise HttpException ( '<STR_LIT>' % parts . scheme ) <EOL> host = parts . netloc <EOL> if not host : <EOL> host = self . host <EOL> if self . port != self . DEFAULT_PORTS [ scheme ] : <EOL> host += "<STR_LIT>" % self . port <EOL> path = parts . path <EOL> if parts . query : <EOL> path += '<STR_LIT:?>' + parts . query <EOL> if scheme != self . scheme : <EOL> raise HttpException ( "<STR_LIT>" % <EOL> ( scheme , self . scheme ) ) <EOL> if not headers : <EOL> headers = HttpHeaders ( ) <EOL> headers . setdefault ( '<STR_LIT>' , '<STR_LIT>' % VERSION ) <EOL> headers . setdefault ( '<STR_LIT>' , host ) <EOL> if body is not None : <EOL> headers [ '<STR_LIT>' ] = str ( len ( body ) ) <EOL> yield write_request ( self . client , method , path , headers , body ) <EOL> response = yield read_response ( self . client ) <EOL> yield Return ( response ) <EOL> def close ( self ) : <EOL> self . client . close ( ) <EOL> def is_closed ( self ) : <EOL> return self . client is None or self . client . is_closed ( ) <EOL> @ classmethod <EOL> @ _o <EOL> def query ( cls , url , headers = None , method = '<STR_LIT:GET>' , body = None ) : <EOL> self = cls ( ) <EOL> parts = urlparse . urlsplit ( url ) <EOL> host = parts . hostname <EOL> port = parts . port or self . DEFAULT_PORTS [ parts . scheme ] <EOL> if not self . client or self . client . is_closed ( ) : <EOL> yield self . connect ( host , port , scheme = parts . scheme ) <EOL> elif not ( self . host , self . port ) == ( host , port ) : <EOL> self . client . close ( ) <EOL> yield self . connect ( host , port , scheme = parts . scheme ) <EOL> try : <EOL> result = yield self . request ( url , headers , method , body ) <EOL> finally : <EOL> self . close ( ) <EOL> yield Return ( result ) <EOL> def extract_response ( value ) : <EOL> if isinstance ( value , basestring ) : <EOL> return ( <NUM_LIT:200> , HttpHeaders ( ) , value ) <EOL> if isinstance ( value , int ) : <EOL> return ( value , HttpHeaders ( ) , "<STR_LIT>" ) <EOL> if len ( value ) == <NUM_LIT:2> : <EOL> return ( value [ <NUM_LIT:0> ] , HttpHeaders ( ) , value [ <NUM_LIT:1> ] ) <EOL> return value <EOL> class HttpRouter ( object ) : <EOL> named_param_re = re . compile ( r'<STR_LIT>' ) <EOL> def __init__ ( self ) : <EOL> self . routes = collections . defaultdict ( list ) <EOL> @ classmethod <EOL> def path_matches ( cls , path , pattern ) : <EOL> m = pattern . match ( path ) <EOL> if not m : <EOL> return False , None <EOL> if not m . end ( ) == len ( path ) : <EOL> return False , None <EOL> return True , m . groupdict ( ) <EOL> def mk_decorator ( self , method , pattern , add_head = False ) : <EOL> if not hasattr ( pattern , '<STR_LIT>' ) : <EOL> pattern = re . escape ( pattern ) <EOL> pattern = pattern . replace ( r'<STR_LIT>' , '<STR_LIT:?>' ) <EOL> pattern = pattern . replace ( r'<STR_LIT>' , '<STR_LIT::>' ) <EOL> pattern = pattern . replace ( r'<STR_LIT>' , '<STR_LIT:_>' ) <EOL> pattern = pattern . replace ( r'<STR_LIT>' , '<STR_LIT:/>' ) <EOL> pattern = pattern . replace ( r'<STR_LIT>' , '<STR_LIT>' ) <EOL> pattern = self . named_param_re . sub ( r'<STR_LIT>' , pattern ) <EOL> pattern = re . compile ( "<STR_LIT>" + pattern + "<STR_LIT:$>" ) <EOL> def decorator ( f ) : <EOL> handler = _o ( f ) <EOL> self . routes [ method ] . append ( ( pattern , handler ) ) <EOL> if add_head : <EOL> self . routes [ '<STR_LIT>' ] . append ( ( pattern , handler ) ) <EOL> return handler <EOL> return decorator <EOL> def get ( self , pattern , add_head = True ) : <EOL> return self . mk_decorator ( '<STR_LIT:GET>' , pattern , add_head = add_head ) <EOL> def post ( self , pattern ) : <EOL> return self . mk_decorator ( '<STR_LIT:POST>' , pattern ) <EOL> def put ( self , pattern ) : <EOL> return self . mk_decorator ( '<STR_LIT>' , pattern ) <EOL> def delete ( self , pattern ) : <EOL> return self . mk_decorator ( '<STR_LIT>' , pattern ) <EOL> def head ( self , pattern ) : <EOL> return self . mk_decorator ( '<STR_LIT>' , pattern ) <EOL> def options ( self , pattern ) : <EOL> return self . mk_decorator ( '<STR_LIT>' , pattern ) <EOL> def patch ( self , pattern ) : <EOL> return self . mk_decorator ( '<STR_LIT>' , pattern ) <EOL> def route_match ( self , req ) : <EOL> for pattern , handler in self . routes [ req . method ] : <EOL> match , kwargs = self . path_matches ( urllib2 . unquote ( req . path ) , <EOL> pattern ) <EOL> if match : <EOL> return handler , kwargs <EOL> return None , None <EOL> @ _o <EOL> def request_handler_wrapper ( self , req , handler , ** kwargs ) : <EOL> resp = yield handler ( req , ** kwargs ) <EOL> yield Return ( resp ) <EOL> @ _o <EOL> def handle_request ( self , req ) : <EOL> before = time . time ( ) <EOL> resp = None <EOL> handler , kwargs = self . route_match ( req ) <EOL> if handler : <EOL> resp = yield self . request_handler_wrapper ( req , handler , ** kwargs ) <EOL> if self . handler and not resp : <EOL> resp = yield self . request_handler_wrapper ( req , self . handler ) <EOL> if not resp : <EOL> resp = ( <NUM_LIT> , { } , "<STR_LIT>" ) <EOL> after = time . time ( ) <EOL> content_length = <NUM_LIT:0> <EOL> if len ( resp ) > <NUM_LIT:2> : <EOL> content_length = len ( resp [ <NUM_LIT:2> ] ) <EOL> log . info ( "<STR_LIT>" , <EOL> req . remote_ip , <EOL> req . method , req . path , req . proto , <EOL> resp [ <NUM_LIT:0> ] , content_length , ( after - before ) * <NUM_LIT:1000> , <EOL> req . headers . get ( '<STR_LIT>' ) ) <EOL> yield Return ( resp ) <EOL> import monocle <EOL> if monocle . _stack_name == '<STR_LIT>' : <EOL> from monocle . twisted_stack . network . http import * <EOL> elif monocle . _stack_name == '<STR_LIT>' : <EOL> from monocle . tornado_stack . network . http import * </s>
