3
Ah`L                 @   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
   H/tmp/pip-build-9m32_hle/djangorestframework/rest_framework/throttling.pyallow_request   s    zBaseThrottle.allow_requestc             C   sv   |j jd}|j jd}tj}|dk	r`|dks6|dkr:|S |jd}|t|t|  }|j S |rrdj|j 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xffZ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 View
    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 | _| j| j\| _| _d S )Nrate)getattrget_rater   
parse_ratenum_requestsduration)r   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 overriddenN)r   )r   r   r	   r
   r
   r   get_cache_keyI   s    z SimpleRateThrottle.get_cache_keyc             C   sX   t | dds d| jj }t|y| j| j S  tk
rR   d| j }t|Y nX 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krd	S |j 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/   <   i  iQ )smhdr   )NN)r   int)r   r   numZperiodr"   r#   r
   r
   r   r!   a   s    zSimpleRateThrottle.parse_ratec             C   s   | j dkrdS | j||| _| jdkr*dS | jj| jg | _| j | _x*| jrp| jd | j| j krp| jj	  qHW t
| j| jkr| j S | j S )z
        Implement the check to see if the request should be throttled.

        On success calls `throttle_success`.
        On failure calls `throttle_failure`.
        NTr,   )r   r%   keyr   r   historytimernowr#   popr   r"   throttle_failurethrottle_success)r   r   r	   r
   r
   r   r   m   s    


z SimpleRateThrottle.allow_requestc             C   s*   | j jd| j | jj| j| j | j dS )zd
        Inserts the current request's timestamp along with the key
        into the cache.
        r   T)r6   insertr8   r   setr5   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.
        r,   r   Nr4   )r6   r#   r8   r"   r   float)r   Zremaining_durationZavailable_requestsr
   r
   r   r      s    zSimpleRateThrottle.wait)r   r   r   r   default_cacher   timer7   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 jrd S | j| j| j|d S )N)r&   ident)useris_authenticatedrA   r&   r   )r   r   r	   r
   r
   r   r%      s
    zAnonRateThrottle.get_cache_keyN)r   r   r   r   r&   r%   r
   r
   r
   r   rB      s   rB   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.
    rD   c             C   s.   |j jr|j j}n
| j|}| j| j|d S )N)r&   rC   )rD   rE   pkr   rA   r&   )r   r   r	   rC   r
   r
   r   r%      s    

zUserRateThrottle.get_cache_keyN)r   r   r   r   r&   r%   r
   r
   r
   r   rF      s   rF   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 | _| j| j\| _| _t j	||S )NT)
r   
scope_attrr&   r    r   r!   r"   r#   superr   )r   r   r	   )r'   r
   r   r      s    
z ScopedRateThrottle.allow_requestc             C   s.   |j jr|j j}n
| j|}| 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.
        )r&   rC   )rD   rE   rG   r   rA   r&   )r   r   r	   rC   r
   r
   r   r%      s    

z ScopedRateThrottle.get_cache_key)	r   r   r   r   rI   r$   r   r%   __classcell__r
   r
   )r'   r   rH      s
   rH   )r   r@   Zdjango.core.cacher   r?   Zdjango.core.exceptionsr   Zrest_framework.settingsr   r   r   rB   rF   rH   r
   r
   r
   r   <module>   s   &s