a
    còfƒ  ã                   @   s‚   d Z ddlZddlmZ ddlmZ ddlmZ G dd„ dƒZ	G dd	„ d	e	ƒZ
G d
d„ de
ƒZG dd„ de
ƒZG dd„ de
ƒZdS )z'
Provides various throttling policies.
é    N)Úcache)ÚImproperlyConfigured)Úapi_settingsc                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚBaseThrottlez&
    Rate throttling of requests.
    c                 C   s   t dƒ‚dS )zT
        Return `True` if the request should be allowed, `False` otherwise.
        z#.allow_request() must be overriddenN©ÚNotImplementedError©ÚselfÚrequestÚview© r   úV/home/httpd/docs/test/DocsMgr/lib/python3.9/site-packages/rest_framework/throttling.pyÚallow_request   s    zBaseThrottle.allow_requestc                 C   sv   |j  d¡}|j  d¡}tj}|dur`|dks6|du r:|S | d¡}|t|t|ƒƒ  }| ¡ S |rrd | ¡ ¡S |S )zå
        Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
        if present and number of proxies is > 0. If not use all of
        HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
        ZHTTP_X_FORWARDED_FORZREMOTE_ADDRNr   ú,Ú )	ZMETAÚgetr   ZNUM_PROXIESÚsplitÚminÚlenÚstripÚjoin)r	   r
   ZxffÚremote_addrZnum_proxiesÚaddrsÚclient_addrr   r   r   Ú	get_ident   s    
zBaseThrottle.get_identc                 C   s   dS )zm
        Optionally, return a recommended number of seconds to wait before
        the next request.
        Nr   ©r	   r   r   r   Úwait*   s    zBaseThrottle.waitN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r   r      s   r   c                   @   sh   e Zd ZdZeZejZdZdZ	e
jZdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )ÚSimpleRateThrottlea¡  
    A simple cache implementation, that only requires `.get_cache_key()`
    to be overridden.

    The rate (requests / seconds) is set by a `rate` attribute on the Throttle
    class.  The attribute is a string of the form 'number_of_requests/period'.

    Period should be one of: ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day')

    Previous request information used for throttling is stored in the cache.
    zthrottle_%(scope)s_%(ident)sNc                 C   s.   t | dd ƒs|  ¡ | _|  | j¡\| _| _d S )NÚrate)ÚgetattrÚget_rater"   Ú
parse_rateÚnum_requestsÚdurationr   r   r   r   Ú__init__D   s    
zSimpleRateThrottle.__init__c                 C   s   t dƒ‚dS )z³
        Should return a unique cache-key which can be used for throttling.
        Must be overridden.

        May return `None` if the request should not be throttled.
        z#.get_cache_key() must be overriddenNr   r   r   r   r   Úget_cache_keyI   s    z SimpleRateThrottle.get_cache_keyc                 C   sX   t | ddƒs d| jj }t|ƒ‚z| j| j W S  tyR   d| j }t|ƒ‚Y n0 dS )zR
        Determine the string representation of the allowed request rate.
        ÚscopeNz9You must set either `.scope` or `.rate` for '%s' throttlez+No default throttle rate set for '%s' scope)r#   Ú	__class__r   r   ÚTHROTTLE_RATESr*   ÚKeyError)r	   Úmsgr   r   r   r$   R   s    ÿ
zSimpleRateThrottle.get_ratec                 C   s@   |du rdS |  d¡\}}t|ƒ}dddddœ|d	  }||fS )
z‰
        Given the request rate string, return a two tuple of:
        <allowed number of requests>, <period of time in seconds>
        N)NNú/é   é<   i  i€Q )ÚsÚmÚhÚdr   )r   Úint)r	   r"   ÚnumZperiodr&   r'   r   r   r   r%   a   s    zSimpleRateThrottle.parse_ratec                 C   sŽ   | j du rdS |  ||¡| _| jdu r*dS | j | jg ¡| _|  ¡ | _| jrn| jd | j| j krn| j 	¡  qFt
| jƒ| jkr†|  ¡ S |  ¡ S )z«
        Implement the check to see if the request should be throttled.

        On success calls `throttle_success`.
        On failure calls `throttle_failure`.
        NTéÿÿÿÿ)r"   r)   Úkeyr   r   ÚhistoryÚtimerÚnowr'   Úpopr   r&   Úthrottle_failureÚthrottle_successr   r   r   r   r   m   s    


z SimpleRateThrottle.allow_requestc                 C   s*   | j  d| j¡ | j | j| j | j¡ dS )zd
        Inserts the current request's timestamp along with the key
        into the cache.
        r   T)r:   Úinsertr<   r   Úsetr9   r'   r   r   r   r   r?   †   s    z#SimpleRateThrottle.throttle_successc                 C   s   dS )zP
        Called when a request to the API has failed due to throttling.
        Fr   r   r   r   r   r>   �   s    z#SimpleRateThrottle.throttle_failurec                 C   sP   | j r| j| j| j d   }n| j}| jt| j ƒ d }|dkrDdS |t|ƒ S )zG
        Returns the recommended next request time in seconds.
        r8   r0   r   N)r:   r'   r<   r&   r   Úfloat)r	   Zremaining_durationZavailable_requestsr   r   r   r   •   s    zSimpleRateThrottle.wait)r   r   r   r    Údefault_cacher   Útimer;   Úcache_formatr*   r   ZDEFAULT_THROTTLE_RATESr,   r(   r)   r$   r%   r   r?   r>   r   r   r   r   r   r!   2   s   		r!   c                   @   s   e Zd ZdZdZdd„ ZdS )ÚAnonRateThrottlez–
    Limits the rate of API calls that may be made by a anonymous users.

    The IP address of the request will be used as the unique cache key.
    Zanonc                 C   s*   |j r|j jrd S | j| j|  |¡dœ S ©N©r*   Úident)ÚuserÚis_authenticatedrE   r*   r   r   r   r   r   r)   ­   s    þzAnonRateThrottle.get_cache_keyN©r   r   r   r    r*   r)   r   r   r   r   rF   ¥   s   rF   c                   @   s   e Zd ZdZdZdd„ ZdS )ÚUserRateThrottlezç
    Limits the rate of API calls that may be made by a given user.

    The user id will be used as a unique cache key if the user is
    authenticated.  For anonymous requests, the IP address of the request will
    be used.
    rJ   c                 C   s4   |j r|j jr|j j}n
|  |¡}| j| j|dœ S rG   ©rJ   rK   Úpkr   rE   r*   ©r	   r
   r   rI   r   r   r   r)   Á   s    

þzUserRateThrottle.get_cache_keyNrL   r   r   r   r   rM   ·   s   rM   c                       s4   e Zd ZdZdZdd„ Z‡ fdd„Zdd„ Z‡  ZS )	ÚScopedRateThrottlea,  
    Limits the rate of API calls by different amounts for various parts of
    the API.  Any view that has the `throttle_scope` property set will be
    throttled.  The unique cache key will be generated by concatenating the
    user id of the request, and the scope of the view being accessed.
    Zthrottle_scopec                 C   s   d S )Nr   r   r   r   r   r(   Ö   s    zScopedRateThrottle.__init__c                    sF   t || jd ƒ| _| jsdS |  ¡ | _|  | j¡\| _| _tƒ  	||¡S )NT)
r#   Ú
scope_attrr*   r$   r"   r%   r&   r'   Úsuperr   r   ©r+   r   r   r   Û   s    
z ScopedRateThrottle.allow_requestc                 C   s4   |j r|j jr|j j}n
|  |¡}| j| j|dœ S )zØ
        If `view.throttle_scope` is not set, don't apply this throttle.

        Otherwise generate the unique cache key by concatenating the user id
        with the `.throttle_scope` property of the view.
        rH   rN   rP   r   r   r   r)   ë   s    

þz ScopedRateThrottle.get_cache_key)	r   r   r   r    rR   r(   r   r)   Ú__classcell__r   r   rT   r   rQ   Í   s
   rQ   )r    rD   Zdjango.core.cacher   rC   Zdjango.core.exceptionsr   Zrest_framework.settingsr   r   r!   rF   rM   rQ   r   r   r   r   Ú<module>   s   &s