Создать веб-сервер, используя ТОЛЬКО стандартную библиотеку - PullRequest
1 голос
/ 08 мая 2020

Я хотел бы реализовать веб-страницу в Python, используя ТОЛЬКО библиотеку std.

Я сделал это в PHP, но хочу сделать это в Python, и мне очень трудно понять документацию.

Это то, что я сделал в PHP:

Доступ http://localhost: 8888 / project / src / car. php.

Пользователь должен заполнить форму, в которой он указывает марку автомобиля.
Затем сайт возвращает JSON список автомобилей в http://localhost: 8888 / project / src / автомобиль. php? марка = toyota
Работает очень хорошо.

Это было очень просто в PHP, но я не смог найти способ сделать это в Python, используя только стандартную библиотеку.
Есть ли у вас какие-нибудь предложения?

Это это то, что у меня есть до сих пор:

server.py:

import http.server
import socketserver

if __name__ == '__main__':
    PORT = 8888
    Handler = http.server.SimpleHTTPRequestHandler
    with socketserver.TCPServer(("", PORT), Handler) as httpd:
        print("serving at port", PORT)
        httpd.serve_forever()

index. html:

<!-- used to make a form for the user -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Autocompletion</title>
</head>
<body>
<h2>Manufacturer finder</h2>

<p>
    Please enter your research
</p>

<form action="car.py" method="get" class="form-example">
    <div class="form-example">
        <label for="brand">Enter your query: </label>
        <input type="text" name="brand" id="brand" required>
    </div>
    <div class="form-example">
        <input type="submit" value="Submit">
    </div>
</form>

</body>
</html>

Пользователь попадает в index. html у которого есть форма, которую нужно заполнить. Когда пользователь заполняет форму, открывается файл: http://localhost: 8888 / car.py? Brand = toyota

Скрипт работает в http://localhost: 8888 / , а не http://localhost: 8888 / car.py (как и мой PHP скрипт), но это не проблема.

После заполнения формы я не Не знаю, как получить переменную производителя и отобразить список автомобилей этой марки. Внутри car.py у меня есть список автомобилей для каждой марки, которая мне просто нужна, поэтому мне просто нужно получить нужные автомобили от этой марки и распечатать его как JSON только без дополнительных HTML.

У меня проблема: заполнив форму, просто распечатайте весь файл car.py.

Незащищенная форма - это не проблема (где вы можете получить результаты, добавив? Brand = toyota на URL-адрес).

Вот как я запускаю сервер:

python server.py

Есть ли у вас предложения?
Спасибо за внимание

1 Ответ

1 голос
/ 08 мая 2020

В документации для выбранного вами класса обработчика довольно четко указано

Этот класс обслуживает файлы из текущего каталога и ниже, напрямую сопоставляя структуру каталогов с HTTP-запросами. .

, поэтому вы видите содержимое car.py.

Вам нужно будет реализовать свой собственный класс обработчика, производный от BaseHTTPRequestHandler, для обслуживания вашего потребности. Этот простой пример только анализирует и возвращает строку запроса как JSON при доступе к /data.

В стороне, сравнивая PHP и Python здесь («это было легко в PHP» ) скорее яблоко-апельсины; с PHP у вас также есть что-то (будь то Apache, Nginx, PHP -FPM, PHP встроенный веб-сервер) для обработки запросов и выбора сценария для использования, его вызова, et c., при этом здесь все делается с нуля.

import urllib.parse
import http.server
import socketserver
import json


class CarHandler(http.server.SimpleHTTPRequestHandler):
    def _send_content(self, data, status=200, content_type="text/plain"):
        if isinstance(data, str):
            data = data.encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", content_type)
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)
        self.wfile.flush()

    def do_GET(self):
        url = urllib.parse.urlparse(self.path)
        if url.path == "/":
            return self._send_content(
                "<form method=get action=/data><input type=search name=q><input type=submit></form>",
                content_type="text/html",
            )
        elif url.path == "/data":
            qs = urllib.parse.parse_qs(url.query)
            return self._send_content(json.dumps(qs), content_type="application/json")
        else:
            return self._send_content(f"404: {url}", status=400)


if __name__ == "__main__":
    PORT = 8891
    with socketserver.TCPServer(("", PORT), CarHandler) as httpd:
        print("serving at port", PORT)
        httpd.serve_forever()
...