# Python : Pallets : Werkzeug \[ [pypi](https://pypi.org/project/Werkzeug/) | [src](https://github.com/pallets/werkzeug/) | [docs](https://werkzeug.palletsprojects.com/en/3.0.x/) ] A comprehensive WSGI web application library. The foundation Flask is built on. - an in-browser interactive debugger (inspect stack traces & source) - request & response objects with all HTTP features - routing system for mapping URLs to endpoints and generating URLs for endpoints - utilities for entity tags, cache control, dates, user agents, cookies, files, etc - a threaded WSGI server for development - a test client for simulating requests without a server All the functionality provided by the `Request` and `Response` objects (aka the “wrappers”) is also available in small utility functions. ###### WSGI "Hello World" ```python application( environ, start_response ): start_response( "200 OK", [ ( "Content-Type", "text/plain" ) ] ) return [ "Hello World!" ] ``` ###### Imports ```python # for apps from werkzeug.serving import run_simple from werkzeug.wrappers import Request, Response # for testing from werkzeug.test import Client, create_environ, EnvironBuilder, run_wsgi_app from werkzeug.testapp import test_app # low-level from werkzeug.datastructures import Headers ``` ###### Werkzeug "Hello World" ```python @Request.application def app( request ): return Response( "Hello, World!" ) if __name__ == "__main__": from werkzeug.serving import run_simple run_simple( "localhost", 4000, app ) ``` #### API ###### Request ```python request = Request( environ ) request.args[ name ] # MultiDict request.data # bytes request.files[ name ] # ImmutableMultiDict, FileStorage objects request.form[ name ] # ImmutableMultiDict request.environ # WSGIEnvironment request.headers[ name ] # Headers request.host # "localhost:8080" request.method # "GET" request.path # "/foo" request.script_root # "" request.url # "http://localhost:8080/foo" ``` ###### Response ```python response = Response( "content" ) response.content_length response.data # bytes response.date # datetime response.get_data( as_text=True ) # string response.headers # Headers response.headers.getlist( "Set-Cookie" ) response.set_cookie( name, value ) response.status # "404 Not Found" response.status_code # 404 response.www_authenticate.set_basic( "..." ) # same as headers[ "www-authenticate" ] # response is a WSGI app return response( environ, start_response ) ``` #### Testing ###### Client & Response ```python c = Client( test_app ) response = c.get( "/" ) # request methods return TestResponse, which builds on Response # If `data` is a dict, # Content-Type is set to "multipart/form-data" (if files) or "application/x-www-form-urlenc response = c.post( data={ "name": "test", "file": ( BytesIO( "file contents".encode( "utf8" ) ), "test.txt" ) } ) # If `data` is a string, bytes, or file-life object, set Content-Type yourself: response = c.post( data="a: value\nb: 1\n", content_type="application/yaml" ) # If `json`, automatically cllas json.dumps() and sets Content-Type to "application/json". response = c.post( "/api", json={ "a": "value", "b": 1 } ) obj = response.json() response.history response.request # Request response.request.environ # WSGIEnvironment ``` ###### Environs A WSGI environment is a dictionary containing HTTP request variables as described in [PEP 3333](https://peps.python.org/pep-3333/#environ-variables). ```python # create_environ() and EnvironBuilder() take the same args (path, query_string, method, etc) environ = create_environ( ... ) -> WSGIEnvironment builder = EnvironBuilder( ... ) -> EnvironBuilder builder = EnvironBuilder.from_environ( environ ) -> EnvironBuilder environ = builder.get_environ() -> WSGIEnvironment request = builder.get_request() -> Request run_wsgi_app( app, environ ) -> ( app_iter, status, headers ) ```