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

Узнай цену своей работы

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

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

Решение задачи: «Простой веб-сервер с directories walk»

textual
Листинг программы
  1. import time,os,sys
  2. import socket
  3. import mimetypes
  4. from urllib.parse import quote,unquote
  5. from subprocess import Popen
  6. #для автоопределения кодировки файлов
  7. from chardet.universaldetector import UniversalDetector
  8.  
  9. ENCODING = "utf-8"
  10.  
  11.  
  12. def read_file(filepath,encoding):
  13.     result = None
  14.     detector = UniversalDetector()
  15.     detector.reset()
  16.    
  17.     for line in open(filepath, 'rb'):
  18.         detector.feed(line)
  19.         if detector.done: break
  20.     detector.close()
  21.     encoding = detector.result.get('encoding') or encoding
  22.    
  23.     print("DETECT:",encoding)
  24.    
  25.     try:
  26.         with open(filepath,encoding=encoding) as f:
  27.             result = f.read()
  28.     except:
  29.         pass
  30.     return result,encoding
  31.  
  32. def generate_html(root):
  33.    
  34.     answer = """<!DOCTYPE html>"""
  35.     answer += """<html><head><title>%s</title>""" % root
  36.     answer += """</head><body><h1>[%s]</h1><ul>"""  % root
  37.     format = """
  38.    <li><a  href='javascript: document.location.href=
  39. "{proto}://{server}:{port}/{relpath}";'>{name}</a></li>
  40. """
  41.    
  42.     # сортировка файлов и директорий - первыми идут каталоги
  43.     dirs  = []
  44.     files = []
  45.     for name in os.listdir(root):
  46.         if os.path.isdir(os.path.join(root,name)):
  47.             dirs.append(name.upper() + "/")
  48.         else:
  49.             files.append(name)
  50.    
  51.     dirs.sort()
  52.     files.sort()
  53.     dirs.extend(files)
  54.    
  55.     for name in dirs:
  56.         relpath = name                                              
  57.         if root != ROOT:                                            
  58.             relpath =  os.path.join(root.replace(ROOT,""),name)
  59.        
  60.         answer += format.format(proto="http",
  61.                                 server=SERVER,
  62.                                 port=PORT,
  63.                                 root=root,
  64.                                 name=name,
  65.                                 relpath=quote(relpath.replace('\\','/').lstrip('/')))
  66.    
  67.     answer += """</ul></body></html>"""
  68.     return answer
  69.  
  70. def send_answer(conn,
  71.                 method="GET",
  72.                 protocol = "HTTP/1.1",
  73.                 status="200 OK",
  74.                 charset="utf-8",
  75.                 typ="text/plain",
  76.                 data=""):
  77.    
  78.     data = data.encode(charset)
  79.     headers = [
  80.         "{} {} {}".format(method, protocol, status),
  81.         "Server: %s" % "simplehttp",
  82.         "Connection: %s" % "close",
  83.         "Content-Type: %s; charset=%s" % (typ,charset),
  84.         "Content-Length: %s" % len(data),
  85.        ]
  86.     print('-' * 10)
  87.     print("RESPONSE:")
  88.     for header in headers:
  89.         conn.send(header.encode(ENCODING) + b"\r\n")    
  90.         print(header)
  91.    
  92.     conn.send(b"\r\n") # после пустой строки в HTTP начинаются данные
  93.     conn.send(data)
  94.    
  95.    
  96. def route(conn, addr):# обработка соединения в отдельной функции
  97.     data = b""
  98.    
  99.     while not b"\r\n" in data: # ждём первую строку
  100.         tmp = conn.recv(1024)
  101.         if not tmp:   # сокет закрыли, пустой объект
  102.             break
  103.         else:
  104.             data += tmp
  105.    
  106.     if not data:      # данные не пришли
  107.         return        # не обрабатываем
  108.        
  109.     udata = data.decode(ENCODING)
  110.     print('-' * 10)
  111.     print('REQUEST:')
  112.     print(udata.split("\r\n\r\n")[0])
  113.    
  114.     # берём первую строку из клиентского запроса
  115.     udata = udata.split("\r\n", 1)[0]
  116.    
  117.     # разбиваем по пробелам
  118.     method, address, protocol = udata.split(" ", 2)
  119.     #print(method, address, protocol)
  120.    
  121.     filepath = os.path.join(ROOT,address.strip('/').replace('/','\\'))
  122.     typ,enc = mimetypes.guess_type(filepath)
  123.     filepath = unquote(filepath)
  124.     print('-'* 10)
  125.     print(filepath,typ)
  126.    
  127.     if address == "/":
  128.         answer = generate_html(ROOT)
  129.         return send_answer(conn,
  130.                             typ="text/html",
  131.                             charset=ENCODING,
  132.                             data=answer)
  133.     else:                        
  134.    
  135.         if os.path.exists(filepath):
  136.             if os.path.isdir(filepath):
  137.                 answer = generate_html(filepath)
  138.                 send_answer(conn,
  139.                             typ="text/html",
  140.                             charset=ENCODING,
  141.                             data=answer)
  142.                
  143.             # если файл имеет читабельное текстовое содержимое - выводим его
  144.             elif typ == "text/plain":
  145.                 text = None
  146.                 error = 'None'
  147.                 try:
  148.                     text,charset =  read_file(filepath,encoding=ENCODING)
  149.                 except Exception as err:        
  150.                     error = str(err)
  151.                
  152.                 if text is not None:
  153.                     send_answer(conn, typ=typ ,charset=charset, data=text)
  154.                 else:
  155.                     send_answer(conn,
  156.                             status="500 Internal Server Error",
  157.                             data= "|".join([error,filepath]))
  158.             # если файл не типа text/plain        
  159.             else:
  160.                 # пробуем открыть его в программе по умолчанию
  161.                 Popen(filepath,shell=True)
  162.                 # генерируем заново список файлов в этом каталоге
  163.                 answer = generate_html(os.path.dirname(filepath))
  164.                 send_answer(conn,
  165.                             typ="text/html",
  166.                             charset=ENCODING,
  167.                             data=answer)
  168.         # если файла не существует          
  169.         else:
  170.             send_answer(conn,
  171.                         status="404 Not Found",
  172.                         data="File not Found:{}".format(filepath)
  173.                         )
  174.            
  175.    
  176. def main(server,port):
  177.     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  178.     sock.bind((server, port))
  179.     sock.listen(5)
  180.  
  181.     try:
  182.         while 1:
  183.             conn, addr = sock.accept()
  184.             print('-' * 10)
  185.             print("Новое подключение: " + addr[0])
  186.            
  187.             try:
  188.                 route(conn, addr)
  189.            
  190.             except Exception as err:
  191.                 print(err)
  192.                 send_answer(conn, "500 Internal Server Error", data=str(err))
  193.            
  194.             finally:
  195.                 # закрываем сокет клиентского подключения
  196.                 conn.close()
  197.     finally:
  198.         sock.close()
  199.  
  200.    
  201. #--------------------------------------------------
  202. if __name__ == "__main__":
  203.     SERVER,PORT = "localhost",8080
  204.     # корневая директория, которая будет доступна по адресу http://localhost:8080
  205.     ROOT = os.path.dirname(__file__)
  206.    
  207.     main(SERVER,PORT)

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

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

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы