def respond_with_json_bytes( request: Request, code: int, json_bytes: bytes, send_cors: bool = False, ): """Sends encoded JSON in response to the given request. Args: request: The http request to respond to. code: The HTTP response code. json_bytes: The json bytes to use as the response body. send_cors: Whether to send Cross-Origin Resource Sharing headers https://fetch.spec.whatwg.org/#http-cors-protocol Returns: twisted.web.server.NOT_DONE_YET if the request is still active. """ request.setResponseCode(code) request.setHeader(b"Content-Type", b"application/json") request.setHeader(b"Content-Length", b"%d" % (len(json_bytes),)) request.setHeader(b"Cache-Control", b"no-cache, no-store, must-revalidate") if send_cors: set_cors_headers(request) # note that this is zero-copy (the bytesio shares a copy-on-write buffer with # the original `bytes`). bytes_io = BytesIO(json_bytes) producer = NoRangeStaticProducer(request, bytes_io) producer.start() return NOT_DONE_YET
def render_POST(self, request): context = self._context(request) form, status, appstruct = self._validate_form(request) if status == 'ok': filename = context['renderer'](appstruct) fileobj = FilePath(filename) request.setHeader('content-disposition', 'attachment; filename="output.pdf"') request.setHeader('content-length', str(fileobj.getsize())) request.setHeader('content-type', 'application/pdf') producer = NoRangeStaticProducer(request, fileobj.open('r')) producer.start() return NOT_DONE_YET data['renderer_form'] = form.render(appstruct) self.render_template(data, request) return NOT_DONE_YET
def respond_with_json_bytes(request, code, json_bytes, send_cors=False, response_code_message=None): """Sends encoded JSON in response to the given request. Args: request (twisted.web.http.Request): The http request to respond to. code (int): The HTTP response code. json_bytes (bytes): The json bytes to use as the response body. send_cors (bool): Whether to send Cross-Origin Resource Sharing headers http://www.w3.org/TR/cors/ Returns: twisted.web.server.NOT_DONE_YET""" request.setResponseCode(code, message=response_code_message) request.setHeader(b"Content-Type", b"application/json") request.setHeader(b"Content-Length", b"%d" % (len(json_bytes),)) request.setHeader(b"Cache-Control", b"no-cache, no-store, must-revalidate") if send_cors: set_cors_headers(request) # todo: we can almost certainly avoid this copy and encode the json straight into # the bytesIO, but it would involve faffing around with string->bytes wrappers. bytes_io = BytesIO(json_bytes) producer = NoRangeStaticProducer(request, bytes_io) producer.start() return NOT_DONE_YET
def respond_with_json_bytes( request, code, json_bytes, send_cors=False, response_code_message=None ): """Sends encoded JSON in response to the given request. Args: request (twisted.web.http.Request): The http request to respond to. code (int): The HTTP response code. json_bytes (bytes): The json bytes to use as the response body. send_cors (bool): Whether to send Cross-Origin Resource Sharing headers http://www.w3.org/TR/cors/ Returns: twisted.web.server.NOT_DONE_YET""" request.setResponseCode(code, message=response_code_message) request.setHeader(b"Content-Type", b"application/json") request.setHeader(b"Content-Length", b"%d" % (len(json_bytes),)) request.setHeader(b"Cache-Control", b"no-cache, no-store, must-revalidate") if send_cors: set_cors_headers(request) # todo: we can almost certainly avoid this copy and encode the json straight into # the bytesIO, but it would involve faffing around with string->bytes wrappers. bytes_io = BytesIO(json_bytes) producer = NoRangeStaticProducer(request, bytes_io) producer.start() return NOT_DONE_YET
def writeResponse(reader): # Some readers from `tftp` do not provide a way to get the size # of the generated content. Only set `Content-Length` when size # can be determined for the response. if hasattr(reader, "size"): request.setHeader(b"Content-Length", reader.size) # The readers from `tftp` use `finish` instead of `close`, but # `NoRangeStaticProducer` expects `close` instead of `finish`. Map # `finish` to `close` so the file handlers are cleaned up. reader.close = reader.finish # Produce the result without allowing range. This producer will # call `close` on the reader and `finish` on the request when done. producer = NoRangeStaticProducer(request, reader) producer.start()
def render_GET(self, request): if self.size: request.setHeader(b'content-length', intToBytes(self.size)) if self.type: request.setHeader(b'content-type', networkString(self.type)) if self.encoding: request.setHeader(b'content-encoding', networkString(self.encoding)) request.setResponseCode(http.OK) # FIXME: depending on self.size, eg when 128kB, we might want to directly return bytes # instead of the overhead setting up a producer etc .. # if we want to serve directly out of ZIP files, we cannot support HTTP # range requests, as the file-like object returned for a file within an archive # does not support seek() (it will raise "not implemented" - 2018/06 with Python 3.6.5) producer = NoRangeStaticProducer(request, self.file) producer.start() # and make sure the connection doesn't get closed return server.NOT_DONE_YET
def _callbackRenderResponseContext( self, request ): self._CleanUpTempFile( request ) response_context = request.hydrus_response_context status_code = response_context.GetStatusCode() request.setResponseCode( status_code ) for ( k, v, kwargs ) in response_context.GetCookies(): request.addCookie( k, v, **kwargs ) do_finish = True if response_context.HasBody(): ( mime, body ) = response_context.GetMimeBody() content_type = HC.mime_string_lookup[ mime ] content_length = len( body ) request.setHeader( 'Content-Type', content_type ) request.setHeader( 'Content-Length', str( content_length ) ) request.write( HydrusData.ToByteString( body ) ) elif response_context.HasPath(): path = response_context.GetPath() size = os.path.getsize( path ) if response_context.IsJSON(): mime = HC.APPLICATION_JSON content_type = HC.mime_string_lookup[ mime ] else: mime = HydrusFileHandling.GetMime( path ) ( base, filename ) = os.path.split( path ) content_type = HC.mime_string_lookup[ mime ] + '; ' + filename content_length = size # can't be unicode! request.setHeader( 'Content-Type', str( content_type ) ) request.setHeader( 'Content-Length', str( content_length ) ) request.setHeader( 'Expires', time.strftime( '%a, %d %b %Y %H:%M:%S GMT', time.gmtime( time.time() + 86400 * 365 ) ) ) request.setHeader( 'Cache-Control', str( 86400 * 365 ) ) fileObject = open( path, 'rb' ) producer = NoRangeStaticProducer( request, fileObject ) producer.start() do_finish = False else: content_length = 0 request.setHeader( 'Content-Length', str( content_length ) ) request.hydrus_request_data_usage += content_length self._recordDataUsage( request ) if do_finish: request.finish()
def _callbackRenderResponseContext(self, request): self._CleanUpTempFile(request) if request.channel is None: # Connection was lost, it seems. # no need for request.finish return if request.requestHeaders.hasHeader('Origin'): if self._service.SupportsCORS(): request.setHeader('Access-Control-Allow-Origin', '*') response_context = request.hydrus_response_context status_code = response_context.GetStatusCode() request.setResponseCode(status_code) for (k, v, kwargs) in response_context.GetCookies(): request.addCookie(k, v, **kwargs) do_finish = True if response_context.HasPath(): path = response_context.GetPath() size = os.path.getsize(path) mime = response_context.GetMime() content_type = HC.mime_mimetype_string_lookup[mime] content_length = size (base, filename) = os.path.split(path) content_disposition = 'inline; filename="' + filename + '"' request.setHeader('Content-Type', str(content_type)) request.setHeader('Content-Length', str(content_length)) request.setHeader('Content-Disposition', str(content_disposition)) request.setHeader( 'Expires', time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(time.time() + 86400 * 365))) request.setHeader('Cache-Control', 'max-age={}'.format(86400 * 365)) fileObject = open(path, 'rb') producer = NoRangeStaticProducer(request, fileObject) producer.start() do_finish = False elif response_context.HasBody(): mime = response_context.GetMime() body_bytes = response_context.GetBodyBytes() content_type = HC.mime_mimetype_string_lookup[mime] content_length = len(body_bytes) content_disposition = 'inline' request.setHeader('Content-Type', content_type) request.setHeader('Content-Length', str(content_length)) request.setHeader('Content-Disposition', content_disposition) request.write(body_bytes) else: content_length = 0 if status_code != 204: # 204 is No Content request.setHeader('Content-Length', str(content_length)) self._reportDataUsed(request, content_length) self._reportRequestUsed(request) if do_finish: request.finish()
def stopProducing(self): NoRangeStaticProducer.stopProducing(self) if hasattr(self, 'deferred'): self.deferred.callback(None)
def start(self): NoRangeStaticProducer.start(self) if self.request is None: return defer.succeed(None) self.deferred = defer.Deferred() return self.deferred
def stream_opened(fd): producer = NoRangeStaticProducer(request, fd) producer.start()
def makeProducer(self, request, content_object): request.setResponseCode(OK) # TODO: add full support for multi-part download and upload # TODO: twisted.web.static.File is a nice example for streaming # TODO: For non-local backends twisted.web.Proxy approach should be reused. return NoRangeStaticProducer(request, content_object)
def __init__(self, request, fileObject): NoRangeStaticProducer.__init__(self, request, fileObject) # Add bytesWritten for simplicity self.bytesWritten = 0 self.size = fileObject.length
def makeProducer(self, request, fileForReading): self._setContentHeaders(request) request.setResponseCode(http.OK) return NoRangeStaticProducer(request, fileForReading)
def _callbackRenderResponseContext( self, request ): self._CleanUpTempFile( request ) if request.channel is None: raise HydrusExceptions.ServerException( 'Channel was closed! Probably a connectionLost that was not caught!' ) response_context = request.hydrus_response_context status_code = response_context.GetStatusCode() request.setResponseCode( status_code ) for ( k, v, kwargs ) in response_context.GetCookies(): request.addCookie( k, v, **kwargs ) do_finish = True if response_context.HasPath(): path = response_context.GetPath() size = os.path.getsize( path ) mime = response_context.GetMime() content_type = HC.mime_string_lookup[ mime ] content_length = size ( base, filename ) = os.path.split( path ) content_disposition = 'inline; filename="' + filename + '"' # can't be unicode! request.setHeader( 'Content-Type', str( content_type ) ) request.setHeader( 'Content-Length', str( content_length ) ) request.setHeader( 'Content-Disposition', str( content_disposition ) ) request.setHeader( 'Expires', time.strftime( '%a, %d %b %Y %H:%M:%S GMT', time.gmtime( time.time() + 86400 * 365 ) ) ) request.setHeader( 'Cache-Control', str( 86400 * 365 ) ) fileObject = open( path, 'rb' ) producer = NoRangeStaticProducer( request, fileObject ) producer.start() do_finish = False elif response_context.HasBody(): mime = response_context.GetMime() body = response_context.GetBody() content_type = HC.mime_string_lookup[ mime ] content_length = len( body ) content_disposition = 'inline' request.setHeader( 'Content-Type', content_type ) request.setHeader( 'Content-Length', str( content_length ) ) request.setHeader( 'Content-Disposition', content_disposition ) request.write( HydrusData.ToByteString( body ) ) else: content_length = 0 request.setHeader( 'Content-Length', str( content_length ) ) self._reportDataUsed( request, content_length ) self._reportRequestUsed( request ) if do_finish: request.finish()