Простой веб-сервер с 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)
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д