
    df$                     p    d Z ddlZddlZddlZddlZddlmZmZ ddl	m
Z
 d Zd Zd Zd Z G d	 d
      Zy)zServe GridFS files with Motor and aiohttp.

Requires Python 3.5 or later and aiohttp 3.0 or later.

See the :doc:`/examples/aiohttp_gridfs_example`.
    N)AsyncIOMotorDatabaseAsyncIOMotorGridFSBucket)_hash_gridoutc                 $    | j                  |      S )a&  Override to choose a GridFS file to serve at a URL.

    By default, if a URL pattern like ``/fs/{filename}`` is mapped to this
    :class:`AIOHTTPGridFS`, then the filename portion of the URL is used as the
    filename, so a request for "/fs/image.png" results in a call to
    :meth:`.AsyncIOMotorGridFSBucket.open_download_stream_by_name` with
    "image.png" as the ``filename`` argument. To customize the mapping of path
    to GridFS file, override ``get_gridfs_file`` and return a
    :class:`asyncio.Future` that resolves to a
    :class:`~motor.motor_asyncio.AsyncIOMotorGridOut`.

    For example, to retrieve the file by ``_id`` instead of filename::

        def get_gridfile_by_id(bucket, filename, request):
            # "filename" is interpreted as _id instead of name.
            # Return a Future AsyncIOMotorGridOut.
            return bucket.open_download_stream(file_id=filename)

        client = AsyncIOMotorClient()
        gridfs_handler = AIOHTTPGridFS(client.my_database,
                                       get_gridfs_file=get_gridfile_by_id)

    :Parameters:
      - `bucket`: An :class:`~motor.motor_asyncio.AsyncIOMotorGridFSBucket`
      - `filename`: A string, the URL portion matching {filename} in the URL
        pattern
      - `request`: An :class:`aiohttp.web.Request`
    )open_download_stream_by_name)bucketfilenamerequests      O/home/api-vastappli/venv/lib/python3.12/site-packages/motor/aiohttp/__init__.pyget_gridfs_filer   "   s    < ..x88    c                      y)a5  Override to customize cache control behavior.

    Return a positive number of seconds to trigger aggressive caching or 0
    to mark resource as cacheable, only. 0 is the default.

    For example, to allow image caching::

        def image_cache_time(filename, modified, mime_type):
            if mime_type.startswith('image/'):
                return 3600

            return 0

        client = AsyncIOMotorClient()
        gridfs_handler = AIOHTTPGridFS(client.my_database,
                                       get_cache_time=image_cache_time)

    :Parameters:
      - `filename`: A string, the URL portion matching {filename} in the URL
        pattern
      - `modified`: A datetime, when the matching GridFS file was created
      - `mime_type`: The file's type, a string like "application/octet-stream"
    r    )r	   modified	mime_types      r   get_cache_timer   C   s    0 r   c                      y)a,  Override to modify the response before sending to client.

    For example, to allow image caching::

        def gzip_header(response, gridout):
            response.headers['Content-Encoding'] = 'gzip'

        client = AsyncIOMotorClient()
        gridfs_handler = AIOHTTPGridFS(client.my_database,
                                       set_extra_headers=gzip_header)

    :Parameters:
      - `response`: An :class:`aiohttp.web.Response`
      - `gridout`: The :class:`~motor.motor_asyncio.AsyncIOMotorGridOut` we
        will serve to the client
    Nr   )responsegridouts     r   set_extra_headersr   ^   s    r   c                     	 | j                   j                  j                  j                         d   }d|z  }t        j                  j                  |      d # t        t
        f$ r d| z  }Y 7w xY w)N	formatterz<Bad AIOHTTPGridFS route "%s", requires a {filename} variablez'Bad AIOHTTPGridFS route for request: %stext)	
match_inforouteresourceget_infoKeyErrorAttributeErroraiohttpwebHTTPInternalServerError)r
   r   msgs      r   _config_errorr%   q   su    B&&,,55>>@M	LyX
 ++
-
-3
-
7TA	 n% B7'ABs   6A A0/A0c                   ,    e Zd ZdZdeeefdZd Zd Z	y)AIOHTTPGridFSa.  Serve files from `GridFS`_.

    This class is a :ref:`request handler <aiohttp-web-handler>` that serves
    GridFS files, similar to aiohttp's built-in static file server.

    .. code-block:: python

        client = AsyncIOMotorClient()
        gridfs_handler = AIOHTTPGridFS(client.my_database)

        app = aiohttp.web.Application()

        # The GridFS URL pattern must have a "{filename}" variable.
        resource = app.router.add_resource("/fs/{filename}")
        resource.add_route("GET", gridfs_handler)
        resource.add_route("HEAD", gridfs_handler)

        app_handler = app.make_handler()
        server = loop.create_server(app_handler, port=80)

    By default, requests' If-Modified-Since headers are honored, but no
    specific cache-control timeout is sent to clients. Thus each request for
    a GridFS file requires a quick check of the file's ``uploadDate`` in
    MongoDB. Pass a custom :func:`get_cache_time` to customize this.

    :Parameters:
      - `database`: An :class:`AsyncIOMotorDatabase`
      - `get_gridfs_file`: Optional override for :func:`get_gridfs_file`
      - `get_cache_time`: Optional override for :func:`get_cache_time`
      - `set_extra_headers`: Optional override for :func:`set_extra_headers`

    .. _GridFS: https://www.mongodb.com/docs/manual/core/gridfs/
    fsc                     t        |t              st        d|z        || _        t	        | j                  |      | _        || _        || _        || _        y )NzDFirst argument to AIOHTTPGridFS must be AsyncIOMotorDatabase, not %r)	
isinstancer   	TypeError	_databaser   _bucket_get_gridfs_file_get_cache_time_set_extra_headers)selfdatabaseroot_collectionr   r   r   s         r   __init__zAIOHTTPGridFS.__init__   sX     ($89VYaa  "/P /-"3r   c                   K   	 |j                   d   }|j                  dvr-t        j
                  j                  |j                  ddh      	 | j                  | j                  |       d{   }t        j
                  j                         }t        |      }| j                  |j                  |||       | j!                  ||       |j"                  }|Z|j%                  |j&                  j(                        }|j&                  j%                  d	
      }	||	k\  r|j+                  d       |S |j,                  j/                  d      }
|
'|
j1                  d      |k(  r|j+                  d       |S |j2                  |_        |j7                  |       d{    |j                  dk(  rkd	}||j2                  k  rZ|j9                  |j:                         d{   }|j=                  |       d{    |t?        |      z  }||j2                  k  rZ|S # t        $ r t        |       Y #w xY w7 # t        j                  $ r0}t        j
                  j                  |j                        |d}~ww xY w7 7 7 w)z&Send filepath to client using request.r	   )GETHEADr6   r7   )methodallowed_methodsNr   tzinfor   )microsecondi0  zIf-None-Match") r   r   r%   r8   r!   r"   HTTPMethodNotAllowedr.   r-   gridfsNoFileHTTPNotFoundpathStreamResponser   _set_standard_headersr0   if_modified_sincereplaceupload_dater;   
set_statusheadersgetstriplengthcontent_lengthprepareread
chunk_sizewritelen)r1   r
   r	   r   erespchecksum	ims_valueif_sincer   etagwrittenchunks                r   __call__zAIOHTTPGridFS.__call__   sJ    	#))*5H >>0++22~~v 3  	E 11$,,'RRG {{))+ !)""7<<wI 	g. --	  !((0C0C0J0J(KH**22q2AH8#$ ""?3

38 ;OOC K%nnll7###>>U"GGNN*%ll7+=+=>>jj'''3u:%	 GNN*
 g  	#'"	# S}} 	E++***=1D	E@ 	$ ?'s   J	H ;J	 H= /H:0H= 4D*J	JAJ	!J"J	:J;!J	J	H73J	6H77J	:H= =J +I;;J  J	J	J	c                 J   |j                   |_        |j                  }|t        j                  |      \  }}|r||_        d|z  |j
                  d<   | j                  ||j                   |j                        }|dkD  rt        j                  j                  t        j                  j                        j                  d       t        j                  |      z   j                  d      |j
                  d<   dt        |      z   |j
                  d	<   y d
|j
                  d	<   y )Nz"%s"Etagr   r:   )secondsz%a, %d %b %Y %H:%M:%S GMTExpireszmax-age=zCache-Controlpublic)rG   last_modifiedcontent_type	mimetypes
guess_typerI   r/   datetimenowtimezoneutcrF   	timedeltastrftimestr)r1   rB   rT   r   rU   rb   encoding
cache_times           r   rD   z#AIOHTTPGridFS._set_standard_headers   s    $00++%.%9%9$%?"L( ,D%0V ))$0C0CWEYEYZ
>!!%%h&7&7&;&;<DDDDQ$$Z89h23 LL#
 -7Z,HDLL),4DLL)r   N)
__name__
__module____qualname____doc__r   r   r   r4   r[   rD   r   r   r   r'   r'   |   s&     J '%+4&7r5r   r'   )rq   re   rc   aiohttp.webr!   r?   motor.motor_asyncior   r   motor.motor_gridfsr   r   r   r   r%   r'   r   r   r   <module>ru      s@        N ,
9B6&BE5 E5r   