web-dev-qa-db-fra.com

Comment faire fonctionner un serveur http qui servent un chemin spécifique?

voici la hiérarchie de mon projet Python3:

projet
  \
  script.py
  web
    \
    index.html

De script.py, Je voudrais lancer un serveur http qui sert le contenu du dossier web.

Ici on suggère ce code pour exécuter un serveur http simple:

import http.server
import socketserver

PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", PORT), Handler)
print("serving at port", PORT)
httpd.serve_forever()

mais cela sert en fait project, pas web. Comment puis-je spécifier le chemin du dossier que je veux servir?

34
roipoussiere

https://docs.python.org/3/library/http.server.html#http.server.SimpleHTTPRequestHandler

Cette classe sert les fichiers du répertoire en cours et des répertoires inférieurs, mappant directement la structure de répertoires aux requêtes HTTP.

Il suffit donc de changer le répertoire en cours avant de démarrer le serveur - voir os.chdir

par exemple:

import http.server
import socketserver
import os

PORT = 8000

web_dir = os.path.join(os.path.dirname(__file__), 'web')
os.chdir(web_dir)

Handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", PORT), Handler)
print("serving at port", PORT)
httpd.serve_forever()
26
John Carter

Si vous voulez seulement servir un fichier statique, vous pouvez le faire en exécutant le module SimpleHTTPServer avec python 2:

 python -m SimpleHTTPServer

Ou avec python 3:

 python3 -m http.server

De cette façon, vous n'avez pas besoin d'écrire de script.

22

Dans Python 3.7 SimpleHTTPRequestHandler peut prendre un argument de directory.) :

import http.server
import socketserver

PORT = 8000
DIRECTORY = "web"


class Handler(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory=DIRECTORY, **kwargs)


with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()

et depuis la ligne de commande:

python -m http.server --directory web

Pour devenir un peu fou ... vous pouvez créer des gestionnaires pour des répertoires arbitraires:

def handler_from(directory):
    def _init(self, *args, **kwargs):
        return http.server.SimpleHTTPRequestHandler.__init__(self, *args, directory=self.directory, **kwargs)
    return type(f'HandlerFrom<{directory}>',
                (http.server.SimpleHTTPRequestHandler,),
                {'__init__': _init, 'directory': directory})


with socketserver.TCPServer(("", PORT), handler_from("web")) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()
19
Andy Hayden

Juste pour être complet, voici comment vous pouvez configurer les classes de serveur afin de servir les fichiers depuis un répertoire arbitraire:

try
    # python 2
    from SimpleHTTPServer import SimpleHTTPRequestHandler
    from BaseHTTPServer import HTTPServer as BaseHTTPServer
except ImportError:
    # python 3
    from http.server import HTTPServer as BaseHTTPServer, SimpleHTTPRequestHandler


class HTTPHandler(SimpleHTTPRequestHandler):
    """This handler uses server.base_path instead of always using os.getcwd()"""
    def translate_path(self, path):
        path = SimpleHTTPRequestHandler.translate_path(self, path)
        relpath = os.path.relpath(path, os.getcwd())
        fullpath = os.path.join(self.server.base_path, relpath)
        return fullpath


class HTTPServer(BaseHTTPServer):
    """The main server, you pass in base_path which is the path you want to serve requests from"""
    def __init__(self, base_path, server_address, RequestHandlerClass=HTTPHandler):
        self.base_path = base_path
        BaseHTTPServer.__init__(self, server_address, RequestHandlerClass)

Ensuite, vous pouvez définir n'importe quel chemin arbitraire dans votre code:

web_dir = os.path.join(os.path.dirname(__file__), 'web')
httpd = HTTPServer(web_dir, ("", 8000))
httpd.serve_forever()
14
Jaymon