コード例 #1
0
 async def read_body(self, receive):
     """Reads a HTTP body from an ASGI connection."""
     # Use the tempfile that auto rolls-over to a disk file as it fills up.
     body_file = tempfile.SpooledTemporaryFile(
         max_size=settings.FILE_UPLOAD_MAX_MEMORY_SIZE, mode="w+b")
     while True:
         message = await receive()
         if message["type"] == "http.disconnect":
             # Early client disconnect.
             raise RequestAborted()
         # Add a body chunk from the message, if provided.
         if "body" in message:
             body_file.write(message["body"])
         # Quit out if that's the end.
         if not message.get("more_body", False):
             break
     body_file.seek(0)
     return body_file
コード例 #2
0
ファイル: handler.py プロジェクト: sinwar/jchat
 def __init__(self, message):
     self.message = message
     self.reply_channel = self.message.reply_channel
     self._content_length = 0
     self._post_parse_error = False
     self.resolver_match = None
     # Path info
     self.path = self.message['path']
     self.script_name = self.message.get('root_path', '')
     if self.script_name:
         # TODO: Better is-prefix checking, slash handling?
         self.path_info = self.path[len(self.script_name):]
     else:
         self.path_info = self.path
     # HTTP basics
     self.method = self.message['method'].upper()
     self.META = {
         "REQUEST_METHOD": self.method,
         "QUERY_STRING": self.message.get('query_string', ''),
         "SCRIPT_NAME": self.script_name,
         # Old code will need these for a while
         "wsgi.multithread": True,
         "wsgi.multiprocess": True,
     }
     if self.message.get('client', None):
         self.META['REMOTE_ADDR'] = self.message['client'][0]
         self.META['REMOTE_HOST'] = self.META['REMOTE_ADDR']
         self.META['REMOTE_PORT'] = self.message['client'][1]
     if self.message.get('server', None):
         self.META['SERVER_NAME'] = self.message['server'][0]
         self.META['SERVER_PORT'] = self.message['server'][1]
     # Handle old style-headers for a transition period
     if "headers" in self.message and isinstance(self.message['headers'],
                                                 dict):
         self.message['headers'] = [
             (x.encode("latin1"), y)
             for x, y in self.message['headers'].items()
         ]
     # Headers go into META
     for name, value in self.message.get('headers', []):
         name = name.decode("latin1")
         if name == "content-length":
             corrected_name = "CONTENT_LENGTH"
         elif name == "content-type":
             corrected_name = "CONTENT_TYPE"
         else:
             corrected_name = 'HTTP_%s' % name.upper().replace("-", "_")
         # HTTPbis say only ASCII chars are allowed in headers, but we latin1 just in case
         value = value.decode("latin1")
         if corrected_name in self.META:
             value = self.META[corrected_name] + "," + value.decode(
                 "latin1")
         self.META[corrected_name] = value
     # Pull out request encoding if we find it
     if "CONTENT_TYPE" in self.META:
         self.content_type, self.content_params = cgi.parse_header(
             self.META["CONTENT_TYPE"])
         if 'charset' in self.content_params:
             try:
                 codecs.lookup(self.content_params['charset'])
             except LookupError:
                 pass
             else:
                 self.encoding = self.content_params['charset']
     else:
         self.content_type, self.content_params = "", {}
     # Pull out content length info
     if self.META.get('CONTENT_LENGTH', None):
         try:
             self._content_length = int(self.META['CONTENT_LENGTH'])
         except (ValueError, TypeError):
             pass
     # Body handling
     self._body = message.get("body", b"")
     if message.get("body_channel", None):
         body_handle_start = time.time()
         while True:
             # Get the next chunk from the request body channel
             chunk = None
             while chunk is None:
                 # If they take too long, raise request timeout and the handler
                 # will turn it into a response
                 if time.time(
                 ) - body_handle_start > self.body_receive_timeout:
                     raise RequestTimeout()
                 _, chunk = message.channel_layer.receive_many(
                     [message['body_channel']],
                     block=True,
                 )
             # If chunk contains close, abort.
             if chunk.get("closed", False):
                 raise RequestAborted()
             # Add content to body
             self._body += chunk.get("content", "")
             # Exit loop if this was the last
             if not chunk.get("more_content", False):
                 break
     assert isinstance(self._body, six.binary_type), "Body is not bytes"
     # Add a stream-a-like for the body
     self._stream = BytesIO(self._body)
     # Other bits
     self.resolver_match = None