o
    hP                     @   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      t d)zT
        Return `True` if the request should be allowed, `False` otherwise.
        z#.allow_request() must be overriddenNotImplementedErrorselfrequestview r   a/var/www/html/magazine_api/magazine_env/lib/python3.10/site-packages/rest_framework/throttling.pyallow_request   s   zBaseThrottle.allow_requestc                 C   sv   |j d}|j d}tj}|dur0|dks|du r|S |d}|t|t|  }| S |r9d| 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      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   r   )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 overriddenr   r	   r   r   r   get_cache_keyI   s   z SimpleRateThrottle.get_cache_keyc                 C   sP   t | ddsd| jj }t|z| j| j W S  ty'   d| j }t|w )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  iQ )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rD| jd | j| j krD| j	  | jrD| jd | j| j ks1t
| j| jkrP|  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   setr:   r(   r   r   r   r   r@      s   z#SimpleRateThrottle.throttle_successc                 C   r   )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r"dS |t| S )zG
        Returns the recommended next request time in seconds.
        r9   r1   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                   @      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| |d S Nr+   ident)useris_authenticatedrF   r+   r   r	   r   r   r   r*      s   zAnonRateThrottle.get_cache_keyNr   r   r    r!   r+   r*   r   r   r   r   rH      s    rH   c                   @   rG   )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.
    rL   c                 C   .   |j jr	|j j}n| |}| j| j|d S rI   rL   rM   pkr   rF   r+   r
   r   r   rK   r   r   r   r*      s   

zUserRateThrottle.get_cache_keyNrN   r   r   r   r   rO      s    rO   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   rP   )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.
        rJ   rQ   rS   r   r   r   r*      s   

z ScopedRateThrottle.get_cache_key)	r   r   r    r!   rU   r)   r   r*   __classcell__r   r   rW   r   rT      s    rT   )r!   rE   Zdjango.core.cacher   rD   Zdjango.core.exceptionsr   Zrest_framework.settingsr   r   r"   rH   rO   rT   r   r   r   r   <module>   s    &s