Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reject invalid HTTP methods and resources #1019

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion docs/content/exporting/http/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,23 @@ chain is used (see Python [ssl.SSLContext.load_default_certs()](https://docs.pyt
from prometheus_client import start_http_server

start_http_server(8000, certfile="server.crt", keyfile="server.key")
```
```

# Supported HTTP methods

The prometheus client will handle the following HTTP methods and resources:

* `OPTIONS (any)` - returns HTTP status 200 and an 'Allow' header indicating the
allowed methods (OPTIONS, GET)
* `GET (any)` - returns HTTP status 200 and the metrics data
* `GET /favicon.ico` - returns HTTP status 200 and an empty response body. Some
browsers support this to display the returned icon in the browser tab.

Other HTTP methods than these are rejected with HTTP status 405 "Method Not Allowed"
and an 'Allow' header indicating the allowed methods (OPTIONS, GET).

Any returned HTTP errors are also displayed in the response body after a hash
sign and with a brief hint. Example:
```
# HTTP 405 Method Not Allowed: XXX; use OPTIONS or GET
```
14 changes: 13 additions & 1 deletion prometheus_client/exposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,24 @@ def prometheus_app(environ, start_response):
accept_header = environ.get('HTTP_ACCEPT')
accept_encoding_header = environ.get('HTTP_ACCEPT_ENCODING')
params = parse_qs(environ.get('QUERY_STRING', ''))
if environ['PATH_INFO'] == '/favicon.ico':
method = environ['REQUEST_METHOD']

if method == 'OPTIONS':
status = '200 OK'
headers = [('Allow', 'OPTIONS,GET')]
output = b''
elif method != 'GET':
status = '405 Method Not Allowed'
headers = [('Allow', 'OPTIONS,GET')]
output = '# HTTP {}: {}; use OPTIONS or GET\n'.format(status, method).encode()
elif environ['PATH_INFO'] == '/favicon.ico':
# Serve empty response for browsers
status = '200 OK'
headers = [('', '')]
output = b''
else:
# Note: For backwards compatibility, the URI path for GET is not
# constrained to the documented /metrics, but any path is allowed.
# Bake output
status, headers, output = _bake_output(registry, accept_header, accept_encoding_header, params, disable_compression)
# Return output
Expand Down