U
    uc<                     @   s   d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddl
mZmZ ddlmZmZ dd	lmZmZmZmZmZ d
d ZG dd deZG dd deZG dd dZdd Zdd ZedZdd ZdS )zwHTTP Request Parser

This server uses asyncore to accept connections and do initial
processing but threads to do work.
    )BytesION)parse)unquote_to_bytes)OverflowableBuffer)ChunkedReceiverFixedStreamReceiver)HEADER_FIELD_REONLY_DIGIT_RE)
BadRequestRequestEntityTooLargeRequestHeaderFieldsTooLargeServerNotImplementedfind_double_newlinec                 C   s   t | dS )Nlatin-1)r   decode)Z
bytestring r   3/tmp/pip-unpacked-wheel-yalm6hg1/waitress/parser.pyunquote_bytes_to_wsgi$   s    r   c                   @   s   e Zd ZdS )ParsingErrorN__name__
__module____qualname__r   r   r   r   r   (   s   r   c                   @   s   e Zd ZdS )TransferEncodingNotImplementedNr   r   r   r   r   r   ,   s   r   c                   @   sl   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdZdZdd Zd	d
 Zdd Zdd Zdd ZdS )HTTPRequestParserzA structure that collects the HTTP request.

    Once the stream is completed, the instance is passed to
    a server task constructor.
    F    r   N1.0c                 C   s   i | _ || _dS )z/
        adj is an Adjustments object.
        N)headersadj)selfr   r   r   r   __init__H   s    zHTTPRequestParser.__init__c              
   C   s4  | j r
dS t|}| j}|dkr| jj}| j| }t|}d}|dkr`|| _|t||  }n|  j|7  _|}| j|kr| d t	d| | _
d| _ |S |dkr|d| }| }|sd| _d| _ nz| | W nr tk
r }	 zt|	jd | _
d| _ W 5 d}	~	X Y n tk
rN }	 zt|	jd | _
d| _ W 5 d}	~	X Y nHX | jdkrbd| _ | jdkr| jj}
| j|
krtd|
 | _
d| _ d| _|S || _|S ||}|  j|7  _| jj}
| j|
krtd|
 | _
d| _ n@|j
r|j
| _
d| _ n(|j r,d| _ | jr,t| | jd< |S dS )z
        Receives the HTTP stream for one request.  Returns the number of
        bytes consumed.  Sets the completed flag once both the header and the
        body have been received.
        r   Ns   GET / HTTP/1.0
zexceeds max_header of %sTzexceeds max_body of %sCONTENT_LENGTH)	completedlenbody_rcvr   Zmax_request_header_sizeheader_plusr   header_bytes_receivedparse_headerr   errorlstripemptyr   r
   argsr   r   content_lengthZmax_request_body_sizer   headers_finishedreceivedbody_bytes_receivedchunkedstr__len__r   )r   dataZdatalenbrZ
max_headersindexconsumedr%   eZmax_bodyr   r   r   r.   Q   s|    





zHTTPRequestParser.receivedc              	   C   s  | d}|dkr4|d|  }||d d }ntdd|ksLd|krTtd|| _t|}| j}|D ]}t|}|std	|d
d\}}	d|krql|		d}	|
 ddd}
z||
  d|	 d7  < W ql tk
r   |	d||
< Y qlX qlt|\}}}|d| _|d}|d}|| _|| _t|\| _| _| _| _| _| jj| _|dd}|dkr| dkrd| _|dkrF|dd}dd |dD }|D ]}|dkrtdq|r
|d dkr
d| _ t!| jj"}t#|| _$n|rtd|dd }|d k| _%| d!krFd| _| j s|d"d#}t&|'dsttd$t(|}|| _)|dkrt!| jj"}t*||| _$dS )%zp
        Parses the header_plus block of text (the headers plus the
        first line of the request).
           
r   N   zHTTP message header invalid      
z#Bare CR or LF found in HTTP messagezInvalid headernamevalue   _s    	   -r   s   , Z
CONNECTION r   z
keep-aliveTz1.1ZTRANSFER_ENCODINGc                 S   s   g | ]}|r| d  qS )z 	)striplower).0encodingr   r   r   
<listcomp>  s     z2HTTPRequestParser.parse_header.<locals>.<listcomp>,>   r0   z-Transfer-Encoding requested is not supported.r0   ZEXPECTz100-continuecloser!   0zContent-Length is invalid)+findrstripr   
first_lineget_header_linesr   r   matchgrouprB   upperreplacer   KeyErrorcrack_first_linerequest_uricommandversion	split_uriproxy_schemeZproxy_netlocpathqueryfragmentr   Z
url_schemegetrC   connection_closepopsplitr   r0   r   Zinbuf_overflowr   r$   expect_continuer	   encodeintr,   r   )r   r%   r6   rM   headerlinesr   linekeyr>   key1rV   urirW   
connectionte	encodingsrE   bufexpectZclr   r   r   r'      s    







		


zHTTPRequestParser.parse_headerc                 C   s    | j }|d k	r| S t S d S N)r$   getfiler   r   r$   r   r   r   get_body_streamK  s    z!HTTPRequestParser.get_body_streamc                 C   s   | j }|d k	r|   d S ro   )r$   ZgetbufrI   rq   r   r   r   rI   S  s    zHTTPRequestParser.close)r   r   r   __doc__r"   r*   ra   r-   r%   r0   r,   r&   r/   r$   rW   r(   r^   r    r.   r'   rr   rI   r   r   r   r   r   0   s(   	w r   c                 C   s   d } } } }}| d d dkrZ| }d|kr@| dd\}}d|kr| dd\}}n6zt| \}}}}}W n tk
r   tdY nX |d|dt||d|dfS )	Nr   r:   s   //   #      ?zBad URIr   )r`   r   urlsplitUnicodeErrorr   r   r   )ri   schemenetlocrZ   r[   r\   r   r   r   rX   Z  s"    	rX   c                 C   s   g }|  d}|D ]h}|sqd|ks,d|kr>tdt|d |drp|s^tdt|d |d  |7  < q|| q|S )	zL
    Splits the header into lines, putting multi-line headers together.
    r9   r;   r<   z'Bare CR or LF found in header line "%s"r   )       	zMalformed header line "%s"rH   )r`   r   r1   
startswithappend)rd   rre   rf   r   r   r   rN   ~  s    

rN   sL   ([^ ]+) ((?:[^ :?#]+://[^ ?#/]*(?:[0-9]{1,5})?)?[^ ]+)(( HTTP/([0-9.]+))$|$)c                 C   s   t | }|d k	rx| t| krx|dr8|d}nd}|d}|| krdtdt|d |d}|||fS dS d S )	N      r   ru   zMalformed HTTP method "%s"r   r:   )r   r   r   )first_line_rerO   endr#   rP   rQ   r   r1   )rf   mrW   methodri   r   r   r   rT     s    




rT   ) rs   ior   reurllibr   urllib.parser   Zwaitress.buffersr   Zwaitress.receiverr   r   Zwaitress.rfc7230r   r	   Zwaitress.utilitiesr
   r   r   r   r   r   	Exceptionr   r   r   rX   rN   compiler   rT   r   r   r   r   <module>   s(   	  ,$