diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index 1197b575c00455..37ac7069cab107 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -167,6 +167,13 @@ provides three different variants: header (using :meth:`send_header`) in all of its responses to clients. For backwards compatibility, the setting defaults to ``'HTTP/1.0'``. + .. attribute:: default_content_type + + Specifies the content-type header value sent when the mime-type cannot + be guessed from the file extension of the requested URL. + For backwards compatibility, the setting defaults to + ``'application/octet-stream'``. + .. attribute:: MessageClass Specifies an :class:`email.message.Message`\ -like class to parse HTTP @@ -462,6 +469,16 @@ following command runs an HTTP/1.1 conformant server:: .. versionchanged:: 3.11 Added the ``--protocol`` option. +By default, the server uses the MIME type ``'application/octet-stream'`` for +the ``content-type`` header when the content type cannot be guessed from the +URL's extension (if any). The option ``--default-content-type`` overrides +this default with one of the user's choosing:: + + python -m http.server --default-content-type text/html + +.. versionchanged:: 3.13 + Added the ``--default-content-type`` option. + .. class:: CGIHTTPRequestHandler(request, client_address, server) This class is used to serve either files or output of CGI scripts from the diff --git a/Lib/http/server.py b/Lib/http/server.py index a90c8d34c394db..c75d0b76f5d1dd 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -269,6 +269,7 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): # the client gets back when sending a malformed request line. # Most web servers default to HTTP 0.9, i.e. don't send a status line. default_request_version = "HTTP/0.9" + default_content_type = "application/octet-stream" def parse_request(self): """Parse a request (internal). @@ -907,7 +908,7 @@ def guess_type(self, path): guess, _ = mimetypes.guess_file_type(path) if guess: return guess - return 'application/octet-stream' + return self.default_content_type # Utilities for CGIHTTPRequestHandler @@ -1263,7 +1264,8 @@ def _get_best_family(*address): def test(HandlerClass=BaseHTTPRequestHandler, ServerClass=ThreadingHTTPServer, - protocol="HTTP/1.0", port=8000, bind=None): + protocol="HTTP/1.0", port=8000, bind=None, + content_type=BaseHTTPRequestHandler.default_content_type): """Test the HTTP request handler class. This runs an HTTP server on port 8000 (or the port argument). @@ -1271,6 +1273,7 @@ def test(HandlerClass=BaseHTTPRequestHandler, """ ServerClass.address_family, addr = _get_best_family(bind, port) HandlerClass.protocol_version = protocol + HandlerClass.default_content_type = content_type with ServerClass(addr, HandlerClass) as httpd: host, port = httpd.socket.getsockname()[:2] url_host = f'[{host}]' if ':' in host else host @@ -1301,6 +1304,9 @@ def test(HandlerClass=BaseHTTPRequestHandler, default='HTTP/1.0', help='conform to this HTTP version ' '(default: %(default)s)') + parser.add_argument('--content-type', # parsed into content_type + default=BaseHTTPRequestHandler.default_content_type, + help='sets default content type for unknown extensions') parser.add_argument('port', default=8000, type=int, nargs='?', help='bind to this port ' '(default: %(default)s)') @@ -1330,4 +1336,5 @@ def finish_request(self, request, client_address): port=args.port, bind=args.bind, protocol=args.protocol, + content_type=args.content_type ) diff --git a/Misc/NEWS.d/next/Library/2023-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst b/Misc/NEWS.d/next/Library/2023-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst new file mode 100644 index 00000000000000..38f3396b94d0f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst @@ -0,0 +1 @@ +Adds ability to set default content-type for no extension/unrecognized extension on :mod:`http.server` module.