diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index 1b00b09bf6da7f..b32a75ae589e53 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. + By default, it is set to ``'application/octet-stream'``. + + .. versionadded:: next .. attribute:: MessageClass Specifies an :class:`email.message.Message`\ -like class to parse HTTP @@ -524,6 +531,16 @@ The following options are accepted: .. versionadded:: 3.11 +.. option:: --default-content-type + + Specifies the Content-Type HTTP header. 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):: + + python -m http.server --default-content-type text/html + + .. versionadded:: next + .. option:: --cgi :class:`CGIHTTPRequestHandler` can be enabled in the command line by passing diff --git a/Lib/http/server.py b/Lib/http/server.py index a90c8d34c394db..287712c42c2b48 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,10 @@ def test(HandlerClass=BaseHTTPRequestHandler, default='HTTP/1.0', help='conform to this HTTP version ' '(default: %(default)s)') + parser.add_argument('--content-type', + default=BaseHTTPRequestHandler.default_content_type, + help='default content type for unknown extensions' + '(default: %(default)s)') parser.add_argument('port', default=8000, type=int, nargs='?', help='bind to this port ' '(default: %(default)s)') @@ -1330,4 +1337,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..99ba9bd1820fc1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-25-19-14-07.gh-issue-113471.ZQMpbI.rst @@ -0,0 +1,2 @@ +Allow :mod:`http.server` to set a default content-type when serving +files with an unknown or missing extension.