Простой веб-сервер с directories walk - Python

Формулировка задачи:

В общем, на просторах инета уже многовато поискал информации, но сложновато все структуризировать и создать свой план действия. Смотрим скриншот, что мне нужно. Дальше я бы хотел услышать как мне лучше всего это сделать. Возможно у вас даже есть ссылки на готовое, чтоб можно было засесть и разбирать по строчке сам код.

Код к задаче: «Простой веб-сервер с directories walk - Python»

textual
import time,os,sys
import socket
import mimetypes
from urllib.parse import quote,unquote
from subprocess import Popen
#для автоопределения кодировки файлов
from chardet.universaldetector import UniversalDetector
 
ENCODING = "utf-8"
 
 
def read_file(filepath,encoding):
    result = None
    detector = UniversalDetector()
    detector.reset()
   
    for line in open(filepath, 'rb'):
        detector.feed(line)
        if detector.done: break
    detector.close()
    encoding = detector.result.get('encoding') or encoding
   
    print("DETECT:",encoding)
   
    try:
        with open(filepath,encoding=encoding) as f:
            result = f.read()
    except:
        pass
    return result,encoding
 
def generate_html(root):
   
    answer = """<!DOCTYPE html>"""
    answer += """<html><head><title>%s</title>""" % root
    answer += """</head><body><h1>[%s]</h1><ul>"""  % root
    format = """    <li><a  href='javascript: document.location.href=
"{proto}://{server}:{port}/{relpath}";'>{name}</a></li>
"""
   
    # сортировка файлов и директорий - первыми идут каталоги
    dirs  = []
    files = []
    for name in os.listdir(root):
        if os.path.isdir(os.path.join(root,name)):
            dirs.append(name.upper() + "/")
        else:
            files.append(name)
   
    dirs.sort()
    files.sort()
    dirs.extend(files)
   
    for name in dirs:
        relpath = name                                              
        if root != ROOT:                                            
            relpath =  os.path.join(root.replace(ROOT,""),name)
       
        answer += format.format(proto="http",
                                server=SERVER,
                                port=PORT,
                                root=root,
                                name=name,
                                relpath=quote(relpath.replace('\\','/').lstrip('/')))
   
    answer += """</ul></body></html>"""
    return answer
 
def send_answer(conn,
                method="GET",
                protocol = "HTTP/1.1",
                status="200 OK",
                charset="utf-8",
                typ="text/plain",
                data=""):
   
    data = data.encode(charset)
    headers = [
        "{} {} {}".format(method, protocol, status),
        "Server: %s" % "simplehttp",
        "Connection: %s" % "close",
        "Content-Type: %s; charset=%s" % (typ,charset),
        "Content-Length: %s" % len(data),
       ]
    print('-' * 10)
    print("RESPONSE:")
    for header in headers:
        conn.send(header.encode(ENCODING) + b"\r\n")    
        print(header)
   
    conn.send(b"\r\n") # после пустой строки в HTTP начинаются данные
    conn.send(data)
   
   
def route(conn, addr):# обработка соединения в отдельной функции
    data = b""
   
    while not b"\r\n" in data: # ждём первую строку
        tmp = conn.recv(1024)
        if not tmp:   # сокет закрыли, пустой объект
            break
        else:
            data += tmp
   
    if not data:      # данные не пришли
        return        # не обрабатываем
       
    udata = data.decode(ENCODING)
    print('-' * 10)
    print('REQUEST:')
    print(udata.split("\r\n\r\n")[0])
   
    # берём первую строку из клиентского запроса
    udata = udata.split("\r\n", 1)[0]
   
    # разбиваем по пробелам
    method, address, protocol = udata.split(" ", 2)
    #print(method, address, protocol)
   
    filepath = os.path.join(ROOT,address.strip('/').replace('/','\\'))
    typ,enc = mimetypes.guess_type(filepath)
    filepath = unquote(filepath)
    print('-'* 10)
    print(filepath,typ)
   
    if address == "/":
        answer = generate_html(ROOT)
        return send_answer(conn,
                            typ="text/html",
                            charset=ENCODING,
                            data=answer)
    else:                        
   
        if os.path.exists(filepath):
            if os.path.isdir(filepath):
                answer = generate_html(filepath)
                send_answer(conn,
                            typ="text/html",
                            charset=ENCODING,
                            data=answer)
               
            # если файл имеет читабельное текстовое содержимое - выводим его
            elif typ == "text/plain":
                text = None
                error = 'None'
                try:
                    text,charset =  read_file(filepath,encoding=ENCODING)
                except Exception as err:        
                    error = str(err)
               
                if text is not None:
                    send_answer(conn, typ=typ ,charset=charset, data=text)
                else:
                    send_answer(conn,
                            status="500 Internal Server Error",
                            data= "|".join([error,filepath]))
            # если файл не типа text/plain        
            else:
                # пробуем открыть его в программе по умолчанию
                Popen(filepath,shell=True)
                # генерируем заново список файлов в этом каталоге
                answer = generate_html(os.path.dirname(filepath))
                send_answer(conn,
                            typ="text/html",
                            charset=ENCODING,
                            data=answer)
        # если файла не существует          
        else:
            send_answer(conn,
                        status="404 Not Found",
                        data="File not Found:{}".format(filepath)
                        )
           
   
def main(server,port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind((server, port))
    sock.listen(5)
 
    try:
        while 1:
            conn, addr = sock.accept()
            print('-' * 10)
            print("Новое подключение: " + addr[0])
           
            try:
                route(conn, addr)
           
            except Exception as err:
                print(err)
                send_answer(conn, "500 Internal Server Error", data=str(err))
           
            finally:
                # закрываем сокет клиентского подключения
                conn.close()
    finally:
        sock.close()
 
   
#--------------------------------------------------
if __name__ == "__main__":
    SERVER,PORT = "localhost",8080
    # корневая директория, которая будет доступна по адресу http://localhost:8080
    ROOT = os.path.dirname(__file__)
   
    main(SERVER,PORT)

13   голосов, оценка 4.077 из 5


СОХРАНИТЬ ССЫЛКУ
Похожие ответы