コード例 #1
0
def raise_for_length(req, limit=_MAXLEN):
    # two possible error cases: no length specified, or length exceeds limit
    # raise appropriate exception if either applies
    length = req.content_length
    if length is None:
        raise HTTPLengthRequired
    if length > limit:
        raise HTTPRequestEntityTooLarge("Max size: {0} kB".format(limit /
                                                                  2**10))
コード例 #2
0
def validate_body_length(event):
    content_length = 0
    max_clength = 160000
    if event.request.method == 'POST':
        content_length = event.request.headers.get('Content-Length')
        if not content_length:
            raise HTTPBadRequest(
                'No Content-Length was provided in request header'
            )  # pragam: no cover
    elif event.request.method == 'GET':
        content_length = len(event.request.params.get('geom', ''))

    if int(content_length) > max_clength:
        raise HTTPRequestEntityTooLarge(
            'LineString too large, maximum Content-Length ' +
            'of %s exceeded' % max_clength)
def put_key(request):
    """Uploads new key-retrieval information."""
    # Validate that the request is text/<something>
    if request.content_type:
        if not request.content_type.startswith("text/"):
            raise HTTPUnsupportedMediaType()
    # Validate that the request is not too big
    if request.content_length is None:
        raise HTTPLengthRequired()
    if request.content_length > 8 * 1024:
        raise HTTPRequestEntityTooLarge()
    # Store the uploaded data.
    username = request.matchdict["username"]
    store = request.registry.getUtility(IKeyRetrievalStorage)
    store.set(username, request.body)
    return Response(status=204)
コード例 #4
0
 def linestring(self, value):
     if value is None or value == '':
         raise HTTPBadRequest("Missing parameter geom")
     try:
         geom = geojson.loads(value,
                              object_hook=geojson.GeoJSON.to_instance)
     except ValueError:
         raise HTTPBadRequest("Error loading geometry in JSON string")
     try:
         geomToShape = shape(geom)
     except Exception:
         raise HTTPBadRequest("Error converting JSON to Shape")
     try:
         geomToShape.is_valid
     except Exception:
         raise HTTPBadRequest("Invalid Linestring syntax")
     if len(geomToShape.coords) > self.nb_points_max:
         raise HTTPRequestEntityTooLarge(
             "Request Geometry contains too many points. Maximum number of points allowed: {}, found {}"
             .format(self.nb_points_max, len(geomToShape.coords)))
     self._linestring = geomToShape
コード例 #5
0
 def set_item(self, request):
     """Upload a new item by ID."""
     # Validate the incoming data.
     if request.content_type not in ("application/json", None):
         msg = "Unsupported Media Type: %s" % (request.content_type, )
         raise HTTPUnsupportedMediaType(msg)
     if len(request.body) > MAX_ITEM_SIZE:
         raise HTTPRequestEntityTooLarge()
     try:
         data = json.loads(request.body)
     except ValueError:
         raise HTTPJsonBadRequest(ERROR_MALFORMED_JSON)
     item = self._parse_item(request, data)
     # Check that we're putting it with the right id.
     # Unfortunately we have to *return* the error response here
     # rather than raise it, because raising HTTPForbidden will
     # trigger pyramid's prompt-for-credentials handlers.
     if request.matchdict["item"] != item.get_id():
         return HTTPForbidden("Item ID does not match origin")
     # Pass through to storage.
     # Requires another round-trip through JSON; yuck.
     request.body = json.dumps({"payload": json.dumps(item)})
     return self.controller.set_item(request)
コード例 #6
0
    def process_request(self, request):
        """Consume an event batch request and return an appropriate response.

        The API spec:

            * the payload is a JSON list of objects, each object being an event
            * batches are at most 40 KiB in size
            * messages are signed with HMAC SHA-256

        If the payload is valid, the events it contains will be put onto the
        event queue.  If there are issues with the request, error events will be
        put into the error queue instead.

        """

        request.environ["events.start_time"] = datetime.datetime.utcnow()

        try:
            signature_header = request.headers["X-Signature"]
        except KeyError:
            keyname = request.GET.get("key", "")
            mac = request.GET.get("mac", "")
        else:
            keyname, mac = parse_signature(signature_header)

        try:
            key = self.keystore[keyname]
        except KeyError:
            keyname = "UNKNOWN"
            key = "INVALID"

        if request.content_length > MAXIMUM_BATCH_SIZE:
            self._publish_error(request, keyname, "TOO_BIG")
            return HTTPRequestEntityTooLarge()
        body = request.body

        if not request.headers.get("User-Agent"):
            self._publish_error(request, keyname, "NO_USERAGENT")
            return HTTPBadRequest("no user-agent provided")

        # Handle Gzipped Requests
        if request.headers.get('Content-Encoding') == 'gzip':
            f = StringIO(body)
            try:
                body = gzip.GzipFile(fileobj=f).read()
            except IOError:
                return HTTPBadRequest("invalid gzip content")

        expected_mac = hmac.new(key, body, hashlib.sha256).hexdigest()
        _LOG.debug('Received request with key: %r, mac: %r, expected_mac: %r',
                   key, mac, expected_mac)
        if not constant_time_compare(expected_mac, mac or ""):
            self._publish_error(request, keyname, "INVALID_MAC")
            return HTTPForbidden()

        try:
            batch = json.loads(body)
        except ValueError:
            self._publish_error(request, keyname, "INVALID_PAYLOAD")
            return HTTPBadRequest("invalid json")

        if not isinstance(batch, list):
            self._publish_error(request, keyname, "INVALID_PAYLOAD")
            return HTTPBadRequest("json root object must be a list")

        reserialized_items = []
        for item in batch:
            reserialized = wrap_and_serialize_event(request, item)
            if len(reserialized) > MAXIMUM_EVENT_SIZE:
                self._publish_error(request, keyname, "EVENT_TOO_BIG")
                return HTTPRequestEntityTooLarge()
            reserialized_items.append(reserialized)

        for item in reserialized_items:
            self.event_queue.put(item)

        self.metrics_client.counter("collected.http." + keyname).increment(
            len(reserialized_items))

        headers = {}
        origin = request.headers.get("Origin")
        if origin and is_allowed_origin(origin, self.allowed_origins):
            headers.update(_CORS_HEADERS)

        return Response(headers=headers)
コード例 #7
0
    def process_request(self, request):
        """Consume an event batch request and return an appropriate response.

        The API spec:

            * the payload is a JSON list of objects, each object being an event
            * batches are at most 40 KiB in size
            * messages are signed with HMAC SHA-256

        If the payload is valid, the events it contains will be put onto the
        event queue.  If there are issues with the request, error events will be
        put into the error queue instead.

        """

        request.environ["events.start_time"] = datetime.datetime.utcnow()

        if request.content_length > _MAXIMUM_CONTENT_LENGTH:
            self.stats_client.count("client-error.too-big")
            error = make_error_event(request, "TOO_BIG")
            self.error_queue.put(error)
            return HTTPRequestEntityTooLarge()

        if not request.headers.get("User-Agent"):
            self.stats_client.count("client-error.no-useragent")
            error = make_error_event(request, "NO_USERAGENT")
            self.error_queue.put(error)
            return HTTPBadRequest("no user-agent provided")

        try:
            signature_header = request.headers["X-Signature"]
        except KeyError:
            keyname = request.GET.get("key", "")
            mac = request.GET.get("mac", "")
        else:
            keyname, mac = parse_signature(signature_header)

        key = self.keystore.get(keyname, "INVALID")
        body = request.body
        expected_mac = hmac.new(key, body, hashlib.sha256).hexdigest()
        if not constant_time_compare(expected_mac, mac or ""):
            self.stats_client.count("client-error.invalid-mac")
            error = make_error_event(request, "INVALID_MAC")
            self.error_queue.put(error)
            return HTTPForbidden()

        try:
            batch = json.loads(body)
        except ValueError:
            self.stats_client.count("client-error.invalid-payload")
            error = make_error_event(request, "INVALID_PAYLOAD")
            self.error_queue.put(error)
            return HTTPBadRequest("invalid json")

        if not isinstance(batch, list):
            self.stats_client.count("client-error.invalid-payload")
            error = make_error_event(request, "INVALID_PAYLOAD")
            self.error_queue.put(error)
            return HTTPBadRequest("json root object must be a list")

        reserialized_items = []
        for item in batch:
            reserialized = wrap_and_serialize_event(request, item)
            if len(reserialized) > MAXIMUM_EVENT_SIZE:
                self.stats_client.count("client-error.too-big")
                error = make_error_event(request, "EVENT_TOO_BIG")
                self.error_queue.put(error)
                return HTTPRequestEntityTooLarge()
            reserialized_items.append(reserialized)

        for item in reserialized_items:
            self.event_queue.put(item)

        self.stats_client.count("collected.http", count=len(reserialized_items))

        headers = {}
        origin = request.headers.get("Origin")
        if origin and is_allowed_origin(origin, self.allowed_origins):
            headers.update(_CORS_HEADERS)

        return Response(headers=headers)