ruạṛ
a [��fA � @ s. d Z ddlmZ zddlZejZW n eyB ddlZejZY n0 ddlm Z ddl mZ ddlZddl Z ddlmZ ddlmZ ddlmZ dd lmZ dd lmZ ddlmZ ddlmZ dd lmZ ddlmZ ddlmZmZ ej Z dZ!dZ"dZ#dZ$ej%Z%ej&Z&G dd� de'�Z(G dd� de'�Z)dS )zRequest class.� )�datetimeN)�UUID)�InputWrapper)�http_cookies)�DEFAULT_MEDIA_TYPE)�errors)�request_helpers)�util)�_parse_forwarded_header)� Forwarded)�Handlers)�json)� parse_host�parse_query_stringz5{0:%Y-%m-%d %H:%M:%S} [FALCON] [ERROR] {1} {2}{3} => )�true�True�yes�1�on)�false�False�no�0�off)�CONTENT_TYPE�CONTENT_LENGTHc @ s� e Zd ZdZdZeZdZdZdndd�Z dd� Z e�d �Z e�d �Ze�d�Ze�d�Ze�d �Ze�d�Ze�d�Zedd� �Zedd� �Zedd� �Zedd� �Zedd� �Zedd� �Zedd� �Zedd� �Zed d!� �Zed"d#� �Zed$d%� �Zed&d'� �Z ed(d)� �Z!ed*d+� �Z"ed,d-� �Z#e"Z$ed.d/� �Z%e%Z&ed0d1� �Z'ed2d3� �Z(ed4d5� �Z)ed6d7� �Z*ed8d9� �Z+ed:d;� �Z,ed<d=� �Z-ed>d?� �Z.ed@dA� �Z/edBdC� �Z0edDdE� �Z1edFdG� �Z2edHdI� �Z3edJdK� �Z4edLdM� �Z5dNdO� Z6dPdQ� Z7dodRdS�Z8dpdTdU�Z9dqdVdW�Z:drdXdY�Z;dsdZd[�Z<dtd\d]�Z=dud^d_�Z>dvdadb�Z?dwddde�Z@dxdfdg�ZAeAZBdhdi� ZCdjdk� ZDdldm� ZEdS )y�Requesta�; Represents a client's HTTP request. Note: `Request` is not meant to be instantiated directly by responders. Args: env (dict): A WSGI environment dict passed in from the server. See also PEP-3333. Keyword Arguments: options (dict): Set of global options passed from the API handler. Attributes: env (dict): Reference to the WSGI environ ``dict`` passed in from the server. (See also PEP-3333.) context (dict): Dictionary to hold any data about the request which is specific to your app (e.g. session object). Falcon itself will not interact with this attribute after it has been initialized. context_type (class): Class variable that determines the factory or type to use for initializing the `context` attribute. By default, the framework will instantiate standard ``dict`` objects. However, you may override this behavior by creating a custom child class of ``falcon.Request``, and then passing that new class to `falcon.API()` by way of the latter's `request_type` parameter. Note: When overriding `context_type` with a factory function (as opposed to a class), the function is called like a method of the current Request instance. Therefore the first argument is the Request instance itself (self). scheme (str): URL scheme used for the request. Either 'http' or 'https'. Note: If the request was proxied, the scheme may not match what was originally requested by the client. :py:attr:`forwarded_scheme` can be used, instead, to handle such cases. forwarded_scheme (str): Original URL scheme requested by the user agent, if the request was proxied. Typical values are 'http' or 'https'. The following request headers are checked, in order of preference, to determine the forwarded scheme: - ``Forwarded`` - ``X-Forwarded-For`` If none of these headers are available, or if the Forwarded header is available but does not contain a "proto" parameter in the first hop, the value of :attr:`scheme` is returned instead. (See also: RFC 7239, Section 1) protocol (str): Deprecated alias for `scheme`. Will be removed in a future release. method (str): HTTP method requested (e.g., 'GET', 'POST', etc.) host (str): Host request header field forwarded_host (str): Original host request header as received by the first proxy in front of the application server. The following request headers are checked, in order of preference, to determine the forwarded scheme: - ``Forwarded`` - ``X-Forwarded-Host`` If none of the above headers are available, or if the Forwarded header is available but the "host" parameter is not included in the first hop, the value of :attr:`host` is returned instead. Note: Reverse proxies are often configured to set the Host header directly to the one that was originally requested by the user agent; in that case, using :attr:`host` is sufficient. (See also: RFC 7239, Section 4) port (int): Port used for the request. If the request URI does not specify a port, the default one for the given schema is returned (80 for HTTP and 443 for HTTPS). netloc (str): Returns the 'host:port' portion of the request URL. The port may be ommitted if it is the default one for the URL's schema (80 for HTTP and 443 for HTTPS). subdomain (str): Leftmost (i.e., most specific) subdomain from the hostname. If only a single domain name is given, `subdomain` will be ``None``. Note: If the hostname in the request is an IP address, the value for `subdomain` is undefined. app (str): The initial portion of the request URI's path that corresponds to the application object, so that the application knows its virtual "location". This may be an empty string, if the application corresponds to the "root" of the server. (Corresponds to the "SCRIPT_NAME" environ variable defined by PEP-3333.) uri (str): The fully-qualified URI for the request. url (str): Alias for `uri`. forwarded_uri (str): Original URI for proxied requests. Uses :attr:`forwarded_scheme` and :attr:`forwarded_host` in order to reconstruct the original URI requested by the user agent. relative_uri (str): The path and query string portion of the request URI, omitting the scheme and host. prefix (str): The prefix of the request URI, including scheme, host, and WSGI app (if any). forwarded_prefix (str): The prefix of the original URI for proxied requests. Uses :attr:`forwarded_scheme` and :attr:`forwarded_host` in order to reconstruct the original URI. path (str): Path portion of the request URI (not including query string). Note: `req.path` may be set to a new value by a `process_request()` middleware method in order to influence routing. query_string (str): Query string portion of the request URI, without the preceding '?' character. uri_template (str): The template for the route that was matched for this request. May be ``None`` if the request has not yet been routed, as would be the case for `process_request()` middleware methods. May also be ``None`` if your app uses a custom routing engine and the engine does not provide the URI template when resolving a route. remote_addr(str): IP address of the closest client or proxy to the WSGI server. This property is determined by the value of ``REMOTE_ADDR`` in the WSGI environment dict. Since this address is not derived from an HTTP header, clients and proxies can not forge it. Note: If your application is behind one or more reverse proxies, you can use :py:attr:`~.access_route` to retrieve the real IP address of the client. access_route(list): IP address of the original client, as well as any known addresses of proxies fronting the WSGI server. The following request headers are checked, in order of preference, to determine the addresses: - ``Forwarded`` - ``X-Forwarded-For`` - ``X-Real-IP`` If none of these headers are available, the value of :py:attr:`~.remote_addr` is used instead. Note: Per `RFC 7239`_, the access route may contain "unknown" and obfuscated identifiers, in addition to IPv4 and IPv6 addresses .. _RFC 7239: https://tools.ietf.org/html/rfc7239 Warning: Headers can be forged by any client or proxy. Use this property with caution and validate all values before using them. Do not rely on the access route to authorize requests. forwarded (list): Value of the Forwarded header, as a parsed list of :class:`falcon.Forwarded` objects, or ``None`` if the header is missing. If the header value is malformed, Falcon will make a best effort to parse what it can. (See also: RFC 7239, Section 4) date (datetime): Value of the Date header, converted to a ``datetime`` instance. The header value is assumed to conform to RFC 1123. auth (str): Value of the Authorization header, or ``None`` if the header is missing. user_agent (str): Value of the User-Agent header, or ``None`` if the header is missing. referer (str): Value of the Referer header, or ``None`` if the header is missing. accept (str): Value of the Accept header, or '*/*' if the header is missing. client_accepts_json (bool): ``True`` if the Accept header indicates that the client is willing to receive JSON, otherwise ``False``. client_accepts_msgpack (bool): ``True`` if the Accept header indicates that the client is willing to receive MessagePack, otherwise ``False``. client_accepts_xml (bool): ``True`` if the Accept header indicates that the client is willing to receive XML, otherwise ``False``. cookies (dict): A dict of name/value cookie pairs. (See also: :ref:`Getting Cookies <getting-cookies>`) content_type (str): Value of the Content-Type header, or ``None`` if the header is missing. content_length (int): Value of the Content-Length header converted to an ``int``, or ``None`` if the header is missing. stream: File-like input object for reading the body of the request, if any. This object provides direct access to the server's data stream and is non-seekable. In order to avoid unintended side effects, and to provide maximum flexibility to the application, Falcon itself does not buffer or spool the data in any way. Since this object is provided by the WSGI server itself, rather than by Falcon, it may behave differently depending on how you host your app. For example, attempting to read more bytes than are expected (as determined by the Content-Length header) may or may not block indefinitely. It's a good idea to test your WSGI server to find out how it behaves. This can be particulary problematic when a request body is expected, but none is given. In this case, the following call blocks under certain WSGI servers:: # Blocks if Content-Length is 0 data = req.stream.read() The workaround is fairly straightforward, if verbose:: # If Content-Length happens to be 0, or the header is # missing altogether, this will not block. data = req.stream.read(req.content_length or 0) Alternatively, when passing the stream directly to a consumer, it may be necessary to branch off the value of the Content-Length header:: if req.content_length: doc = json.load(req.stream) For a slight performance cost, you may instead wish to use :py:attr:`bounded_stream`, which wraps the native WSGI input object to normalize its behavior. Note: If an HTML form is POSTed to the API using the *application/x-www-form-urlencoded* media type, and the :py:attr:`~.RequestOptions.auto_parse_form_urlencoded` option is set, the framework will consume `stream` in order to parse the parameters and merge them into the query string parameters. In this case, the stream will be left at EOF. bounded_stream: File-like wrapper around `stream` to normalize certain differences between the native input objects employed by different WSGI servers. In particular, `bounded_stream` is aware of the expected Content-Length of the body, and will never block on out-of-bounds reads, assuming the client does not stall while transmitting the data to the server. For example, the following will not block when Content-Length is 0 or the header is missing altogether:: data = req.bounded_stream.read() This is also safe:: doc = json.load(req.bounded_stream) expect (str): Value of the Expect header, or ``None`` if the header is missing. media (object): Returns a deserialized form of the request stream. When called, it will attempt to deserialize the request stream using the Content-Type header as well as the media-type handlers configured via :class:`falcon.RequestOptions`. See :ref:`media` for more information regarding media handling. Warning: This operation will consume the request stream the first time it's called and cache the results. Follow-up calls will just retrieve a cached version of the object. range (tuple of int): A 2-member ``tuple`` parsed from the value of the Range header. The two members correspond to the first and last byte positions of the requested resource, inclusive. Negative indices indicate offset from the end of the resource, where -1 is the last byte, -2 is the second-to-last byte, and so forth. Only continous ranges are supported (e.g., "bytes=0-0,-1" would result in an HTTPBadRequest exception when the attribute is accessed.) range_unit (str): Unit of the range parsed from the value of the Range header, or ``None`` if the header is missing if_match (str): Value of the If-Match header, or ``None`` if the header is missing. if_none_match (str): Value of the If-None-Match header, or ``None`` if the header is missing. if_modified_since (datetime): Value of the If-Modified-Since header, or ``None`` if the header is missing. if_unmodified_since (datetime): Value of the If-Unmodified-Since header, or ``None`` if the header is missing. if_range (str): Value of the If-Range header, or ``None`` if the header is missing. headers (dict): Raw HTTP headers from the request with canonical dash-separated names. Parsing all the headers to create this dict is done the first time this attribute is accessed. This parsing can be costly, so unless you need all the headers in this format, you should use the `get_header` method or one of the convenience attributes instead, to get a value for a specific header. params (dict): The mapping of request query parameter names to their values. Where the parameter appears multiple times in the query string, the value mapped to that parameter key will be a list of all the values in the order seen. options (dict): Set of global options passed from the API handler. )�__dict__�_bounded_stream�_cached_access_route�_cached_forwarded�_cached_forwarded_prefix�_cached_forwarded_uri�_cached_headers�_cached_prefix�_cached_relative_uri�_cached_uri�_cookies�_params�_wsgierrors�content_type�context�env�method�options�path�query_string�stream�uri_template�_mediaFNc C s� || _ |r|nt� | _|d | _|d | _d | _d | _|d p@d}tjrZ|� d�� dd�}| jjr�t|�dkr�|� d�r�|d d � | _n|| _z|d | _W n ty� d| _i | _Y n*0 | jr�t| j| jj| jjd�| _ni | _d | _d | _d | _d | _d | _d | _d | _d | _d | _z| j d | _W n t�yD d | _Y n0 | j�sht |d t!t"f�t#_$dt#_| j$�r�| �%� | _&| j&| _'n|d | _&d | _'| jj(�r�| jd u�r�d| jv �r�| jdv�r�| �)� | �*� | _+d S )Nzwsgi.errors�REQUEST_METHOD� PATH_INFO�/�latin1�utf-8�replace� ����QUERY_STRING� ��keep_blank_qs_values�parse_qs_csvr � wsgi.inputTz!application/x-www-form-urlencoded)�GET�HEAD),r, �RequestOptionsr. r) r- r2 r3 �six�PY3�encode�decode�strip_url_path_trailing_slash�len�endswithr/ r0 �KeyErrorr( r r? �auto_parse_qs_csvr'