API docs: fresco.util¶
fresco.util.common¶
Common utilities for writing applications in fresco
fresco.util.security¶
Security-related utilities
fresco.util.http¶
Utilities for working with data on the HTTP level
- fresco.util.http.CHUNK_SIZE = 1024¶
Data chunk size to read from the input stream (wsgi.input)
- class fresco.util.http.FileUpload(filename, headers, fileob)[source]¶
Represent a file uploaded in an HTTP form submission
- class fresco.util.http.HTTPMessage(policy=Compat32())[source]¶
Represent HTTP request message headers
- exception fresco.util.http.MissingContentLength(*args, **kwargs)[source]¶
No
Content-Length
header given
- class fresco.util.http.ParsedContentType(content_type, encoding, params)¶
- content_type¶
Alias for field number 0
- encoding¶
Alias for field number 1
- params¶
Alias for field number 2
- fresco.util.http.encode_multipart(data=None, files=None, charset='UTF-8', **kwargs)[source]¶
Encode
data
using multipart/form-data encoding, returning a tuple of(<encoded data>, <environ items>)
.- Parameters:
data – POST data to be encoded, either a dict or list of
(name, value)
tuples.charset – Encoding used for any string values encountered in
data
files – list of
(name, filename, content_type, data)
tuples.data
may be either a byte string, iterator or file-like object.kwargs – other data items as keyword arguments
- Returns:
a tuple of
(<encoded_data>, <environ_items>)
, whereencoded_data
is a BytesIO object andenviron
is a dict containing the Content-Type and Content-Length headers encoded for inclusion in a WSGI environ dict.
- fresco.util.http.get_body_bytes(environ, max_size=16384) bytes [source]¶
Read a single message body from environ[‘wsgi.input’], returning a bytes object.
- fresco.util.http.get_content_type_info(environ, default_type='application/octet-stream', default_encoding='iso-8859-1') ParsedContentType [source]¶
Read and parse the Content-Type header and return a
ParsedContentType
object.
- fresco.util.http.parse_header(header: str | ~email.header.Header, ie_workaround: bool = False, _broken_encoding_sniffer=<built-in method search of re.Pattern object>) Tuple[str, Dict[str, str]] [source]¶
Given a header, return a tuple of
(value, {parameter_name: parameter_value}])
.Example usage:
>>> parse_header("text/html; charset=UTF-8") ('text/html', {'charset': 'UTF-8'}) >>> parse_header("multipart/form-data; boundary=-------7d91772e200be") ('multipart/form-data', {'boundary': '-------7d91772e200be'})
- fresco.util.http.parse_multipart(stream: Iterator[bytes], boundary, default_charset, max_size, ie_workaround=True) Tuple[Iterable[Tuple[str, FileUpload | str]], Callable | None] [source]¶
Parse data encoded as
multipart/form-data
. Return an iterator over tuples of ` (<field-name>, <data>)``, and an optionalclose
function.data
will be a string in the case of a regular input field, or aFileUpload
instance if a file was uploaded.If a
close
function is returned, the caller must call it in order to close any temporary files created at the end of the request lifecycle.- Parameters:
stream – input stream from which to read data
boundary – multipart boundary string, as specified by the
Content-Disposition
headerdefault_charset – character set to use for encoding, if not specified by a content-type header. In practice web browsers don’t supply a content-type header so this needs to contain a sensible value.
max_size – Maximum size in bytes for any non file upload part
ie_workaround – If True (the default), enable a work around for IE’s broken content-disposition header encoding.
- fresco.util.http.parse_parameters(s, preserve_backslashes=False) Dict[str, str] [source]¶
Return
s
parsed as a sequence of semi-colon delimited name=value pairs.Example usage:
>>> from fresco.util.http import parse_parameters >>> parse_parameters('foo=bar') {'foo': 'bar'} >>> parse_parameters('foo="bar\""') {'foo': 'bar"'}
The
preserve_backslashes
flag is used to preserve IE compatibility for file upload paths, which it incorrectly encodes without escaping backslashes, eg:Content-Disposition: form-data; name="file"; filename="C:\tmp\Ext.js"
(To be RFC compliant, the backslashes should be doubled up).
- fresco.util.http.parse_post(environ, _io: IO[bytes], default_charset: str | None = None, max_size=16384, max_multipart_size=2097152, ie_workaround=True) Tuple[Iterable[Tuple[str, FileUpload | str]], Callable | None] [source]¶
Parse the contents of an HTTP POST request, which may be either application/x-www-form-urlencoded or multipart/form-data encoded.
Returned items are either tuples of (name, value) for simple string values or (name, FileUpload) for uploaded files.
- Parameters:
max_multipart_size – Maximum size of total data for a multipart form submission
max_size – The maximum size of data allowed to be read into memory. For a application/x-www-form-urlencoded submission, this is the maximum size of the entire data. For a multipart/form-data submission, this is the maximum size of any individual field (except file uploads).
- fresco.util.http.parse_querystring(data: str, charset: str | None = None, strict: bool = False, keep_blank_values: bool = True) List[Tuple[str, str]] [source]¶
Return
(key, value)
pairs from the given querystring:>>> list(parse_querystring('green%20eggs=ham;me=sam+i+am')) [('green eggs', 'ham'), ('me', 'sam i am')]
- Parameters:
data – The query string to parse.
charset – Character encoding used to decode values. If not specified,
fresco.DEFAULT_CHARSET
will be used.keep_blank_values – if True, keys without associated values will be returned as empty strings. if False, no key, value pair will be returned.
strict – if
True
, aRequestParseError
will be raised on parsing errors.
- fresco.util.http.read_until(stream: Iterator[bytes], delimiter: bytes) Tuple[Iterator[bytes], Iterator[bytes], Callable[[], bool]] [source]¶
Return two iterators over byte stream stream` and a callable which indicates whether the delimiter was found.
The first iterator yields all data up to
delimiter
. The second iterator generates all remaining data.The first iterator must be exhausted before the second is iterated. The callable must only be called after the first iterator has been exhausted.
fresco.util.io¶
Utilities for wrapping IO streams. These are used internally by fresco when parsing wsgi request input streams.
fresco.util.wsgi¶
Utilities for interfacing with WSGI
- class fresco.util.wsgi.ClosingIterator(iterable, *close_funcs)[source]¶
Wrap a WSGI iterator to allow additional close functions to be called on application exit.
Synopsis:
>>> class filelikeobject(object): ... ... def read(self): ... print("file read!") ... return '' ... ... def close(self): ... print("file closed!") ... >>> def app(environ, start_response): ... f = filelikeobject() ... start_response('200 OK', [('Content-Type', 'text/plain')]) ... return ClosingIterator(iter(f.read, ''), f.close) ... >>> from flea import Agent >>> m = Agent(app).get('/') file read! file closed!
- class fresco.util.wsgi.StartResponseWrapper(start_response)[source]¶
Wrapper class for the
start_response
callable, allowing middleware applications to intercept and interrogate the proxied start_response arguments.Synopsis:
>>> def my_wsgi_app(environ, start_response): ... start_response('200 OK', [('Content-Type', 'text/plain')]) ... return ['Whoa nelly!'] ... >>> def my_other_wsgi_app(environ, start_response): ... responder = StartResponseWrapper(start_response) ... result = my_wsgi_app(environ, responder) ... print("Got status", responder.status) ... print("Got headers", responder.headers) ... responder.call_start_response() ... return result ... >>> from flea import Agent >>> result = Agent(my_other_wsgi_app).get('/') Got status 200 OK Got headers [('Content-Type', 'text/plain')]
See also
Response.from_wsgi
, which takes a wsgi callable, environ and start_response, and returns aResponse
object, allowing the client to further interrogate and customize the WSGI response.Note that it is usually not advised to use this directly in middleware as start_response may not be called directly from the WSGI application, but rather from the iterator it returns. In this case the middleware may need logic to accommodate this. It is usually safer to use
Response.from_wsgi
, which takes this into account.
- fresco.util.wsgi.bytes_to_environ(s)[source]¶
Encode a byte string to a WSGI environ value
This returns a ‘bytes-as-unicode’ string.
- fresco.util.wsgi.make_environ(url='/', environ=None, wsgi_input=b'', **kwargs)[source]¶
Return a WSGI environ dict populated with values modelling the specified request url and data.
- Parameters:
url – The URL for the request, eg
/index.html
or/search?q=foo
. Note thaturl
must be properly URL encoded.environ – values to pass into the WSGI environ dict
wsgi_input – The input stream to use in the
wsgi.input
key of the environ dictkwargs – additional keyword arguments will be passed into the WSGI request environment