Commit a17a2f52 authored by Stéphane Wirtel's avatar Stéphane Wirtel Committed by Victor Stinner

bpo-28707: Add the directory parameter to http.server.SimpleHTTPRequestHandler...

bpo-28707: Add the directory parameter to http.server.SimpleHTTPRequestHandler and http.server module (#1776)

* bpo-28707: call the constructor of SimpleHTTPRequestHandler in the test with a mock object

* bpo-28707: Add the directory parameter to http.server.SimpleHTTPRequestHandler and http.server module
parent 07244a83
...@@ -299,7 +299,7 @@ of which this module provides three different variants: ...@@ -299,7 +299,7 @@ of which this module provides three different variants:
delays, it now always returns the IP address. delays, it now always returns the IP address.
.. class:: SimpleHTTPRequestHandler(request, client_address, server) .. class:: SimpleHTTPRequestHandler(request, client_address, server, directory=None)
This class serves files from the current directory and below, directly This class serves files from the current directory and below, directly
mapping the directory structure to HTTP requests. mapping the directory structure to HTTP requests.
...@@ -323,6 +323,10 @@ of which this module provides three different variants: ...@@ -323,6 +323,10 @@ of which this module provides three different variants:
``application/octet-stream``. The mapping is used case-insensitively, ``application/octet-stream``. The mapping is used case-insensitively,
and so should contain only lower-cased keys. and so should contain only lower-cased keys.
.. attribute:: directory
If not specified, the directory to serve is the current working directory.
The :class:`SimpleHTTPRequestHandler` class defines the following methods: The :class:`SimpleHTTPRequestHandler` class defines the following methods:
.. method:: do_HEAD() .. method:: do_HEAD()
...@@ -397,6 +401,14 @@ following command causes the server to bind to localhost only:: ...@@ -397,6 +401,14 @@ following command causes the server to bind to localhost only::
.. versionadded:: 3.4 .. versionadded:: 3.4
``--bind`` argument was introduced. ``--bind`` argument was introduced.
By default, server uses the current directory. The option ``-d/--directory``
specifies a directory to which it should serve the files. For example,
the following command uses a specific directory::
python -m http.server --directory /tmp/
.. versionadded:: 3.7
``--directory`` specify alternate directory
.. class:: CGIHTTPRequestHandler(request, client_address, server) .. class:: CGIHTTPRequestHandler(request, client_address, server)
...@@ -442,4 +454,3 @@ following command causes the server to bind to localhost only:: ...@@ -442,4 +454,3 @@ following command causes the server to bind to localhost only::
the ``--cgi`` option:: the ``--cgi`` option::
python -m http.server --cgi 8000 python -m http.server --cgi 8000
...@@ -139,6 +139,11 @@ If-Modified-Since header. The server returns the 304 response status if the ...@@ -139,6 +139,11 @@ If-Modified-Since header. The server returns the 304 response status if the
target file was not modified after the time specified in the header. target file was not modified after the time specified in the header.
(Contributed by Pierre Quentel in :issue:`29654`.) (Contributed by Pierre Quentel in :issue:`29654`.)
Add the parameter ``directory`` to the :class:`~http.server.SimpleHTTPRequestHandler`
and the ``--directory`` to the command line of the module :mod:`~http.server`.
With this parameter, the server serves the specified directory, by default it uses the current working directory.
(Contributed by Stéphane Wirtel and Julien Palard in :issue:`28707`.)
locale locale
------ ------
......
...@@ -103,6 +103,7 @@ import socketserver ...@@ -103,6 +103,7 @@ import socketserver
import sys import sys
import time import time
import urllib.parse import urllib.parse
from functools import partial
from http import HTTPStatus from http import HTTPStatus
...@@ -634,6 +635,12 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): ...@@ -634,6 +635,12 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
server_version = "SimpleHTTP/" + __version__ server_version = "SimpleHTTP/" + __version__
def __init__(self, *args, directory=None, **kwargs):
if directory is None:
directory = os.getcwd()
self.directory = directory
super().__init__(*args, **kwargs)
def do_GET(self): def do_GET(self):
"""Serve a GET request.""" """Serve a GET request."""
f = self.send_head() f = self.send_head()
...@@ -806,7 +813,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): ...@@ -806,7 +813,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
path = posixpath.normpath(path) path = posixpath.normpath(path)
words = path.split('/') words = path.split('/')
words = filter(None, words) words = filter(None, words)
path = os.getcwd() path = self.directory
for word in words: for word in words:
if os.path.dirname(word) or word in (os.curdir, os.pardir): if os.path.dirname(word) or word in (os.curdir, os.pardir):
# Ignore components that are not a simple file/directory name # Ignore components that are not a simple file/directory name
...@@ -1234,6 +1241,9 @@ if __name__ == '__main__': ...@@ -1234,6 +1241,9 @@ if __name__ == '__main__':
parser.add_argument('--bind', '-b', default='', metavar='ADDRESS', parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
help='Specify alternate bind address ' help='Specify alternate bind address '
'[default: all interfaces]') '[default: all interfaces]')
parser.add_argument('--directory', '-d', default=os.getcwd(),
help='Specify alternative directory '
'[default:current directory]')
parser.add_argument('port', action='store', parser.add_argument('port', action='store',
default=8000, type=int, default=8000, type=int,
nargs='?', nargs='?',
...@@ -1242,5 +1252,6 @@ if __name__ == '__main__': ...@@ -1242,5 +1252,6 @@ if __name__ == '__main__':
if args.cgi: if args.cgi:
handler_class = CGIHTTPRequestHandler handler_class = CGIHTTPRequestHandler
else: else:
handler_class = SimpleHTTPRequestHandler handler_class = partial(SimpleHTTPRequestHandler,
directory=args.directory)
test(HandlerClass=handler_class, port=args.port, bind=args.bind) test(HandlerClass=handler_class, port=args.port, bind=args.bind)
...@@ -22,6 +22,7 @@ import urllib.parse ...@@ -22,6 +22,7 @@ import urllib.parse
import tempfile import tempfile
import time import time
import datetime import datetime
from unittest import mock
from io import BytesIO from io import BytesIO
import unittest import unittest
...@@ -782,7 +783,11 @@ class CGIHTTPServerTestCase(BaseTestCase): ...@@ -782,7 +783,11 @@ class CGIHTTPServerTestCase(BaseTestCase):
class SocketlessRequestHandler(SimpleHTTPRequestHandler): class SocketlessRequestHandler(SimpleHTTPRequestHandler):
def __init__(self): def __init__(self, *args, **kwargs):
request = mock.Mock()
request.makefile.return_value = BytesIO()
super().__init__(request, None, None)
self.get_called = False self.get_called = False
self.protocol_version = "HTTP/1.1" self.protocol_version = "HTTP/1.1"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment