Простой веб-сервер с directories walk - Python
Формулировка задачи:
В общем, на просторах инета уже многовато поискал информации, но сложновато все структуризировать и создать свой план действия. Смотрим скриншот, что мне нужно. Дальше я бы хотел услышать как мне лучше всего это сделать. Возможно у вас даже есть ссылки на готовое, чтоб можно было засесть и разбирать по строчке сам код.
Решение задачи: «Простой веб-сервер с directories walk»
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)
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д