Esempio n. 1
0
    def send_data(self, request):
        """ Handles sending data to host for PUT or PATCH.
        :param request: http request object
        :type request: webob.Request
        :return: http response object
        :rtype: webob.Response
        """
        # For now we require range headers; we could lift this restriction
        # later.  If so, be sure to add conditions to request.headers access
        # below.
        # Note that webob request.headers is case-insensitive.
        if 'Content-Range' not in request.headers:
            raise exc.HTTPBadRequest(
                "Content-Range header required for {} requests".format(
                    request.method))

        resource_id = self.get_resource_id(request)
        imaged_url = self.get_imaged_url(request)

        headers = self.get_default_headers(resource_id)
        headers['Content-Range'] = request.headers['Content-Range']
        headers['Content-Length'] = request.headers['Content-Length']
        max_transfer_bytes = int(headers['Content-Length'])

        body = web.CappedStream(request.body_file, max_transfer_bytes)
        stream = False
        logging.debug("Resource %s: transferring %d bytes to host",
                      resource_id, max_transfer_bytes)
        imaged_response = self.make_imaged_request(request.method, imaged_url,
                                                   headers, body, stream)

        response = server.response(imaged_response.status_code)
        response.headers['Cache-Control'] = 'no-cache, no-store'

        return response
Esempio n. 2
0
    def get(self, res_id):
        resource_id = self.get_resource_id(self.request)
        imaged_url = self.get_imaged_url(self.request)

        headers = self.get_default_headers(resource_id)
        # Note that webob request.headers is case-insensitive.
        if 'Range' in self.request.headers:
            headers['Range'] = self.request.headers['Range']

        body = ""
        stream = True  # Don't let Requests read entire body into memory

        imaged_response = self.make_imaged_request(self.request.method,
                                                   imaged_url, headers, body,
                                                   stream)

        response = server.response(imaged_response.status_code)
        response.headers['Cache-Control'] = 'no-cache, no-store'
        response.headers['Content-Range'] = \
            imaged_response.headers.get('Content-Range', '')
        disposition = imaged_response.headers.get('Content-Disposition')
        if disposition is not None:
            response.headers['Content-Disposition'] = disposition

        max_transfer_bytes = int(imaged_response.headers.get('Content-Length'))
        response.body_file = web.CappedStream(
            RequestStreamAdapter(imaged_response.iter_content(4096, False)),
            max_transfer_bytes)
        response.headers['Content-Length'] = str(max_transfer_bytes)
        logging.debug("Resource %s: transferring %d bytes from host",
                      resource_id, max_transfer_bytes)

        return response
Esempio n. 3
0
    def patch(self, res_id):
        """
        Proxy PATCH request to daemon.
        """
        if not self.request.content_length:
            raise exc.HTTPBadRequest("Content-Length is required")

        # Notes:
        # - PATCH response is not cachable, no need for cache-control.
        # - We cannot have read_timeout since PATCH can take unpredictable
        #   time, depending on size of the modified byte range, and the storage
        #   capabillties.
        res = self.make_imaged_request(
            "PATCH",
            self.get_imaged_url(self.ticket),
            self.request.headers,
            web.CappedStream(self.request.body_file,
                             self.request.content_length),
            False,
            connection_timeout=self.config.imaged_connection_timeout_sec)

        # TODO: We expect empty response from the daemon. If we start to return
        # non-empty response, this must be changed to stream the daemon
        # response to the caller.
        return web.response(res.status_code)
Esempio n. 4
0
    def put(self, res_id):
        """ Handles sending data to host for PUT or PATCH.
        :param request: http request object
        :type request: webob.Request
        :return: http response object
        :rtype: webob.Response
        """
        imaged_url = self.get_imaged_url(self.ticket)
        if "flush" in self.request.params:
            imaged_url += "?flush=" + self.request.params["flush"]

        headers = self.get_default_headers(res_id)
        if 'Content-Length' not in self.request.headers:
            raise exc.HTTPBadRequest("Content-Length header is required")
        headers['Content-Length'] = self.request.headers['Content-Length']
        if 'Content-Range' in self.request.headers:
            headers['Content-Range'] = self.request.headers['Content-Range']

        max_transfer_bytes = int(headers['Content-Length'])
        body = web.CappedStream(self.request.body_file, max_transfer_bytes)
        stream = False
        logging.debug("Resource %s: transferring %d bytes to host", res_id,
                      max_transfer_bytes)
        imaged_response = self.make_imaged_request(
            self.request.method,
            imaged_url,
            headers,
            body,
            stream,
            connection_timeout=self.config.imaged_connection_timeout_sec,
            read_timeout=self.config.imaged_read_timeout_sec)

        response = web.response(imaged_response.status_code)
        response.headers['Cache-Control'] = 'no-cache, no-store'

        return response
Esempio n. 5
0
def test_capped_stream_short_reads():
    stream = ioutil.UnbufferedStream([b"1" * 123, b"2" * 456])
    capped_stream = web.CappedStream(stream, 1024)
    assert capped_stream.read(1024) == b"1" * 123
    assert capped_stream.read(1024) == b"2" * 456
    assert capped_stream.read(1024) == b""
Esempio n. 6
0
def test_capped_stream_read_size():
    stream = io.BytesIO(b"x" * 1024)
    capped_stream = web.CappedStream(stream, 768)
    assert capped_stream.read(123) == b"x" * 123
Esempio n. 7
0
def test_capped_stream_read_default():
    stream = io.BytesIO(b"x" * 8192)
    buffer_size = 4096
    capped_stream = web.CappedStream(stream, 5120, buffer_size=buffer_size)
    assert capped_stream.read() == b"x" * buffer_size
    assert capped_stream.read() == b"x" * 1024
Esempio n. 8
0
def test_capped_stream_buffer_size():
    stream = io.BytesIO(b"x" * 8192)
    buffer_size = 4096
    capped_stream = web.CappedStream(stream, 5120, buffer_size=buffer_size)
    chunks = list(capped_stream)
    assert chunks == [b"x" * buffer_size, b"x" * 1024]
Esempio n. 9
0
def test_capped_stream_iter():
    stream = io.BytesIO(b"x" * 148 * 1024)
    max_bytes = 138 * 1024
    capped_stream = web.CappedStream(stream, max_bytes, buffer_size=128 * 1024)
    data = b"".join(capped_stream)
    assert data == b"x" * max_bytes