예제 #1
0
파일: websocket.py 프로젝트: larbing/pants
    def on_overflow_error(self, exception):
        """
        Placeholder. Called when an internal buffer on the WebSocket has
        exceeded its size limit.

        By default, logs the exception and closes the WebSocket.

        ==========  ============
        Argument    Description
        ==========  ============
        exception   The exception that was raised.
        ==========  ============
        """
        log.exception(exception)
        self.close(reason=1009)
예제 #2
0
    def _read_request_body(self, data):
        """
        Read a request body from the socket, parse it, and then call the
        request handler for the current request.
        """
        request = self.current_request
        request.body = data

        try:
            content_type = request.headers.get('Content-Type', '')
            if request.method in ('POST', 'PUT'):
                if content_type.startswith(
                        'application/x-www-form-urlencoded'):
                    post = request.post
                    for key, val in parse_qsl(data, False):
                        if key in post:
                            if isinstance(post[key], list):
                                post[key].append(val)
                            else:
                                post[key] = [post[key], val]
                        else:
                            post[key] = val

                elif content_type.startswith('multipart/form-data'):
                    for field in content_type.split(';'):
                        key, _, value = field.strip().partition('=')
                        if key == 'boundary' and value:
                            parse_multipart(request, value, data)
                            break
                    else:
                        log.warning('Invalid multipart/form-data.')

        except BadRequest as err:
            log.info('Bad request from %r: %s', self.remote_address, err)

            request.send_response(err.message, err.code)
            self.close()
            return

        try:
            self.server.request_handler(request)
        except Exception:
            log.exception('Error handling HTTP request.')
            if request._started:
                self.close(False)
            else:
                request.send_response("500 Internal Server Error", 500)
                self.close()
예제 #3
0
파일: server.py 프로젝트: larbing/pants
    def _read_request_body(self, data):
        """
        Read a request body from the socket, parse it, and then call the
        request handler for the current request.
        """
        request = self.current_request
        request.body = data

        try:
            content_type = request.headers.get('Content-Type', '')
            if request.method in ('POST','PUT'):
                if content_type.startswith('application/x-www-form-urlencoded'):
                    post = request.post
                    for key, val in parse_qsl(data, False):
                        if key in post:
                            if isinstance(post[key], list):
                                post[key].append(val)
                            else:
                                post[key] = [post[key], val]
                        else:
                            post[key] = val

                elif content_type.startswith('multipart/form-data'):
                    for field in content_type.split(';'):
                        key, _, value = field.strip().partition('=')
                        if key == 'boundary' and value:
                            parse_multipart(request, value, data)
                            break
                    else:
                        log.warning('Invalid multipart/form-data.')

        except BadRequest as err:
            log.info('Bad request from %r: %s',
                self.remote_address, err)

            request.send_response(err.message, err.code)
            self.close()
            return

        try:
            self.server.request_handler(request)
        except Exception:
            log.exception('Error handling HTTP request.')
            if request._started:
                self.close(False)
            else:
                request.send_response("500 Internal Server Error", 500)
                self.close()
예제 #4
0
파일: websocket.py 프로젝트: larbing/pants
    def _safely_call(self, thing_to_call, *args, **kwargs):
        """
        Safely execute a callable.

        The callable is wrapped in a try block and executed. If an
        exception is raised it is logged.

        ==============  ============
        Argument        Description
        ==============  ============
        thing_to_call   The callable to execute.
        *args           The positional arguments to be passed to the callable.
        **kwargs        The keyword arguments to be passed to the callable.
        ==============  ============
        """
        try:
            return thing_to_call(*args, **kwargs)
        except Exception:
            log.exception("Exception raised on %r." % self)
예제 #5
0
    def _read_header(self, data):
        """
        Read the headers of an HTTP request from the socket, and the request
        body if necessary, into a new HTTPRequest instance. Then, assuming that
        the headers are valid, call the server's request handler.
        """
        try:
            initial_line, _, data = data.partition(CRLF)

            try:
                method, url, protocol = WHITESPACE.split(
                    initial_line)  #.split(' ')
            except ValueError:
                raise BadRequest('Invalid HTTP request line.')

            if not protocol.startswith('HTTP/'):
                raise BadRequest('Invalid HTTP protocol version.',
                                 code='505 HTTP Version Not Supported')

            # Parse the headers.
            if data:
                headers = read_headers(data)
            else:
                headers = {}

            # If we're secure, we're HTTPs.
            if self.ssl_enabled:
                scheme = 'https'
            else:
                scheme = 'http'

            # Construct an HTTPRequest object.
            self.current_request = request = HTTPRequest(
                self, method, url, protocol, headers, scheme)

            # If we have a Content-Length header, read the request body.
            length = headers.get('Content-Length')
            if length:
                if not isinstance(length, int):
                    raise BadRequest(
                        'Provided Content-Length (%r) is invalid.' % length)
                elif length > self.server.max_request:
                    raise BadRequest(
                        ('Provided Content-Length (%d) larger than server '
                         'limit %d.') % (length, self.server.max_request),
                        code='413 Request Entity Too Large')

                if headers.get('Expect', '').lower() == '100-continue':
                    self.write("%s 100 (Continue)%s" % (protocol, DOUBLE_CRLF))

                # Await a request body.
                self.on_read = self._read_request_body
                self.read_delimiter = length
                return

        except BadRequest as err:
            log.info('Bad request from %r: %s', self.remote_address, err)

            self.write('HTTP/1.1 %s%s' % (err.code, CRLF))
            if err.message:
                self.write('Content-Type: text/html%s' % CRLF)
                self.write('Content-Length: %d%s' %
                           (len(err.message), DOUBLE_CRLF))
                self.write(err.message)
            else:
                self.write(CRLF)
            self.close()
            return

        except Exception as err:
            log.info('Exception handling request from %r: %s',
                     self.remote_address, err)

            self.write('HTTP/1.1 500 Internal Server Error%s' % CRLF)
            self.write('Content-Length: 0%s' % DOUBLE_CRLF)
            self.close()
            return

        try:
            # Call the request handler.
            self.server.request_handler(request)
        except Exception:
            log.exception('Error handling HTTP request.')
            if request._started:
                self.close(False)
            else:
                request.send_response("500 Internal Server Error", 500)
                self.close()
예제 #6
0
파일: server.py 프로젝트: larbing/pants
    def _read_header(self, data):
        """
        Read the headers of an HTTP request from the socket, and the request
        body if necessary, into a new HTTPRequest instance. Then, assuming that
        the headers are valid, call the server's request handler.
        """
        try:
            initial_line, _, data = data.partition(CRLF)

            try:
                method, uri, protocol = WHITESPACE.split(initial_line) #.split(' ')
            except ValueError:
                raise BadRequest('Invalid HTTP request line.')

            if not protocol.startswith('HTTP/'):
                raise BadRequest('Invalid HTTP protocol version.',
                                 code='505 HTTP Version Not Supported')

            # Parse the headers.
            if data:
                headers = read_headers(data)
            else:
                headers = {}

            # If we're secure, we're HTTPs.
            if self.ssl_enabled:
                scheme = 'https'
            else:
                scheme = 'http'

            # Construct an HTTPRequest object.
            self.current_request = request = HTTPRequest(self,
                method, uri, protocol, headers, scheme)

            # If we have a Content-Length header, read the request body.
            length = headers.get('Content-Length')
            if length:
                if not isinstance(length, int):
                    raise BadRequest(
                        'Provided Content-Length (%r) is invalid.' % length
                        )
                elif length > self.server.max_request:
                    raise BadRequest((
                        'Provided Content-Length (%d) larger than server '
                        'limit %d.'
                        ) % (length, self.server.max_request),
                        code='413 Request Entity Too Large')

                if headers.get('Expect','').lower() == '100-continue':
                    self.write("%s 100 (Continue)%s" % (
                        protocol, DOUBLE_CRLF))

                # Await a request body.
                self.on_read = self._read_request_body
                self.read_delimiter = length
                return

        except BadRequest as err:
            log.info('Bad request from %r: %s',
                self.remote_address, err)
            
            self.write('HTTP/1.1 %s%s' % (err.code, CRLF))
            if err.message:
                self.write('Content-Type: text/html%s' % CRLF)
                self.write('Content-Length: %d%s' % (len(err.message),
                                                     DOUBLE_CRLF))
                self.write(err.message)
            else:
                self.write(CRLF)
            self.close()
            return

        except Exception as err:
            log.info('Exception handling request from %r: %s',
                self.remote_address, err)

            self.write('HTTP/1.1 500 Internal Server Error%s' % CRLF)
            self.write('Content-Length: 0%s' % DOUBLE_CRLF)
            self.close()
            return

        try:
            # Call the request handler.
            self.server.request_handler(request)
        except Exception:
            log.exception('Error handling HTTP request.')
            if request._started:
                self.close(False)
            else:
                request.send_response("500 Internal Server Error", 500)
                self.close()
예제 #7
0
파일: websocket.py 프로젝트: larbing/pants
    def _process_read_buffer(self):
        """
        Process the read_buffer. This is only used when the ReadDelimiter isn't
        EntireMessage.
        """
        while self._read_buffer:
            delimiter = self._read_delimiter

            if delimiter is None or delimiter is EntireMessage:
                data = self._read_buffer
                self._read_buffer = u""
                self._safely_call(self.on_read, data)

            elif isinstance(delimiter, (int, long)):
                if len(self._read_buffer) < delimiter:
                    break
                data = self._read_buffer[:delimiter]
                self._read_buffer = self._read_buffer[delimiter:]
                self._safely_call(self.on_read, data)

            elif isinstance(delimiter, basestring):
                mark = self._read_buffer.find(delimiter)
                if mark == -1:
                    break
                data = self._read_buffer[:mark]
                self._read_buffer = self._read_buffer[mark + len(delimiter):]
                self._safely_call(self.on_read, data)

            elif isinstance(delimiter, Struct):
                if len(self._read_buffer) < delimiter.size:
                    break
                data = self._read_buffer[:delimiter.size]
                self._read_buffer = self._read_buffer[delimiter.size:]

                # Safely unpack it. This should *probably* never error.
                try:
                    data = delimiter.unpack(data)
                except struct.error:
                    log.exception("Unable to unpack data on %r." % self)
                    self.close(False)
                    break

                # Unlike most on_read calls, this one sends every variable of
                # the parsed data as its own argument.
                self._safely_call(self.on_read, *data)

            elif isinstance(delimiter, RegexType):
                # Depending on regex_search, we could do this two ways.
                if self.regex_search:
                    match = delimiter.search(self._read_buffer)
                    if not match:
                        break

                    data = self._read_buffer[:match.start()]
                    self._read_buffer = self._read_buffer[match.end():]

                else:
                    # Require the match to be at the beginning.
                    data = delimiter.match(self._read_buffer)
                    if not data:
                        break

                    self._read_buffer = self._read_buffer[data.end():]

                # Send either the string or the match object.
                self._safely_call(self.on_read, data)

            else:
                log.warning("Invalid read_delimiter on %r." % self)
                break

            if self._connection is None or not self.connected:
                break