# 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 )
```