This will be ``"SimpleHTTP/" + __version__``, where ``__version__`` is
defined at the module level.
+ .. 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:: extensions_map
A dictionary mapping suffixes into MIME types, contains custom overrides
.. versionadded:: 3.11
+.. option:: --content-type <content_type>
+
+ Specifies the default Content-Type HTTP header used when the MIME type
+ cannot be guessed from the URL's file extension. By default, the server
+ uses ``'application/octet-stream'``:
+
+ .. code-block:: bash
+
+ python -m http.server --content-type text/html
+
+ .. versionadded:: next
+
.. option:: --tls-cert
Specifies a TLS certificate chain for HTTPS connections:
<using-on-controlling-color>`.
(Contributed by Hugo van Kemenade in :gh:`146292`.)
+* Added :attr:`~http.server.SimpleHTTPRequestHandler.default_content_type`
+ and the :option:`--content-type <http.server --content-type>` command-line
+ option to allow customizing the default ``Content-Type`` header
+ for files with unknown extensions.
+ (Contributed by John Comeau and Hugo van Kemenade in :gh:`113471`.)
+
inspect
-------
"""
server_version = "SimpleHTTP"
+ default_content_type = "application/octet-stream"
index_pages = ("index.html", "index.htm")
extensions_map = _encodings_map_default = {
'.gz': 'application/gzip',
guess, _ = mimetypes.guess_file_type(path)
if guess:
return guess
- return 'application/octet-stream'
+ return self.default_content_type
nobody = None
return family, sockaddr
-def test(HandlerClass=BaseHTTPRequestHandler,
+def test(HandlerClass=SimpleHTTPRequestHandler,
ServerClass=ThreadingHTTPServer,
protocol="HTTP/1.0", port=8000, bind=None,
+ content_type=SimpleHTTPRequestHandler.default_content_type,
tls_cert=None, tls_key=None, tls_password=None):
"""Test the HTTP request handler class.
"""
ServerClass.address_family, addr = _get_best_family(bind, port)
HandlerClass.protocol_version = protocol
+ HandlerClass.default_content_type = content_type
if tls_cert:
server = ServerClass(addr, HandlerClass, certfile=tls_cert,
default='HTTP/1.0',
help='conform to this HTTP version '
'(default: %(default)s)')
+ parser.add_argument('--content-type',
+ default=SimpleHTTPRequestHandler.default_content_type,
+ help='default content type for unknown extensions '
+ '(default: %(default)s)')
parser.add_argument('--tls-cert', metavar='PATH',
help='path to the TLS certificate chain file')
parser.add_argument('--tls-key', metavar='PATH',
port=args.port,
bind=args.bind,
protocol=args.protocol,
+ content_type=args.content_type,
tls_cert=args.tls_cert,
tls_key=args.tls_key,
tls_password=tls_key_password,
'protocol': default_protocol,
'port': default_port,
'bind': default_bind,
+ 'content_type': 'application/octet-stream',
'tls_cert': None,
'tls_key': None,
'tls_password': None,
mock_func.assert_called_once_with(**call_args)
mock_func.reset_mock()
+ @mock.patch('http.server.test')
+ def test_content_type_flag(self, mock_func):
+ content_types = ['text/html', 'text/plain', 'application/json']
+ for content_type in content_types:
+ with self.subTest(content_type=content_type):
+ self.invoke_httpd('--content-type', content_type)
+ call_args = self.args | dict(content_type=content_type)
+ mock_func.assert_called_once_with(**call_args)
+ mock_func.reset_mock()
+
@unittest.skipIf(ssl is None, "requires ssl")
@mock.patch('http.server.test')
def test_tls_cert_and_key_flags(self, mock_func):