Разбор данных запроса GET с помощью SimpleHTTPServer

Итак, я создал простой сервер на компьютере с Ubuntu на порту 8000, выполнив следующие действия:

python -m SimpleHTTPServer

10.127.11.18 - - [14/Aug/2014 15:11:55] "GET / HTTP/1.1" 200 -
10.127.11.18 - - [14/Aug/2014 15:11:55] code 404, message File not found
10.127.11.18 - - [14/Aug/2014 15:11:55] "GET /favicon.ico HTTP/1.1" 404 -
10.127.11.18 - - [14/Aug/2014 15:12:02] "GET /crazysean/ HTTP/1.1" 200 -
10.127.11.18 - - [14/Aug/2014 15:12:37] "GET /crazysean/ HTTP/1.1" 200 -
10.127.11.18 - - [14/Aug/2014 15:12:52] "GET /crazysean/?url=www.google.com&x=200&y=400 HTTP/1.1" 301 -
10.127.11.18 - - [14/Aug/2014 15:12:52] "GET /crazysean/?url=www.google.com&x=200&y=400/ HTTP/1.1" 200 -
10.127.11.18 - - [14/Aug/2014 15:13:10] "GET /crazysean/?url=www.google.com&x=200&y=400/ HTTP/1.1" 200 -

Я пытаюсь проанализировать отправленные данные GET, такие как URL, позиция x и позиция y.

Я предполагаю, что моим первым шагом должно быть создание нового сценария следующим образом:

import SimpleHTTPServer
import SocketServer

PORT = 8000

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

httpd = SocketServer.TCPServer(("", PORT), Handler)

print "serving at port", PORT
httpd.serve_forever()

Но я не уверен, как внести изменения в этот сценарий, чтобы захватить данные GET, потому что в конечном итоге я хочу сбросить данные в базу данных sqlite3.


person metersk    schedule 14.08.2014    source источник
comment
Вы пытаетесь сохранить проанализированные журналы или пытаетесь сделать что-то еще?   -  person RCA    schedule 14.08.2014
comment
@slipjack Полагаю, сохранение журналов было бы хорошим началом.   -  person metersk    schedule 14.08.2014
comment
@slipjack Я думаю, лучший способ выразить то, что я ищу, - это я хочу анализировать запросы GET по мере их поступления.   -  person metersk    schedule 14.08.2014
comment
Вы бы очень выиграли от использования библиотеки более высокого уровня, такой как flask.   -  person Paulo Scardine    schedule 14.08.2014
comment
@PauloScardine Я понимаю это и относительно хорошо знаю, как использовать flask, но я пытаюсь сделать это в качестве учебного опыта.   -  person metersk    schedule 14.08.2014
comment
Что вы подразумеваете под анализом запросов GET по мере их поступления. SimpleHTTPServer уже анализирует запросы; вот как он их обслуживает и записывает сообщения журнала. Вы хотите перехватить его синтаксический анализ и заменить его своим? Или для доступа к полям, которые он анализирует? Или вы ищете отдельную программу, которая будет анализировать генерируемые журналы? Или…?   -  person abarnert    schedule 14.08.2014
comment
@abarnert Например, где это хранится "GET /crazysean/?url=www.google.com&x=200&y=400 HTTP/1.1" 301 -? Я хочу разобрать URL-адрес, значение x и значение y и сохранить их в базе данных sqlite. Итак, я думаю, из ваших вариантов это доступ к полям, которые он анализирует, верно?   -  person metersk    schedule 14.08.2014
comment
@Meepl: он не хранится. Он проанализирован, зарегистрирован, обслужен и забыт.   -  person abarnert    schedule 14.08.2014
comment
@abarnert, как мне его сохранить?   -  person metersk    schedule 14.08.2014
comment
Фактическая команда похожа на GET HTTP/1.1 /crazysean/?url=www.google.com&x=200&y=400. Вы можете получить части этого, создав подкласс обработчика. Если вам нужна остальная информация журнала, например 301, это не является частью запроса; это обработчик, объясняющий, что он сделал с запросом.   -  person abarnert    schedule 14.08.2014


Ответы (1)


Я думаю, что это XY-проблема. Вы не заинтересованы в разборе GET-запросов или выполнении каких-либо действий с журналами; вам нужно «захватить данные GET» точно так же, как SimpleHTTPServer использует эти данные для обслуживания запросов, чтобы вы могли хранить их в базе данных. И вы только что подумали, что единственный способ сделать это — разобрать что-то, где-то, но вы не знали, что именно.

Очевидно, что SimpleHTTPServer уже должен анализировать данные GET и иметь именно то, что вам нужно. Итак, где это?

Как сказано в документации:

Большая часть работы, например анализ запроса, выполняется базовым классом BaseHTTPServer.BaseHTTPRequestHandler. Этот класс реализует функции do_GET() и do_HEAD().

Перейдите по этой ссылке, и вы увидите:

Обработчик проанализирует запрос и заголовки, а затем вызовет метод, специфичный для типа запроса. Имя метода создается из запроса. Например, для метода запроса SPAM метод do_SPAM() будет вызываться без аргументов. Вся соответствующая информация хранится в переменных экземпляра обработчика…

Итак, все было разобрано на переменные экземпляра; есть хороший список из них под этим абзацем ниже.

So:

class DBLoggingHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super(DBLoggingHandler, self).__init__(*args, **kwargs)
        self.db = sqlite3.connect(dbpath)
    def do_GET(self):
        self.db.execute("INSERT INTO GetLog (command, vers, path) VALUES (?, ?, ?)",
                        (self.command, self.request_version, self.path))
        return super(DBLoggingHandler, self).do_GET()

Если вы хотите разобрать path на отдельные компоненты, вы можете использовать urlparse для этого:

    def do_GET(self):
        bits = urlparse.urlpase(self.path)
        self.db.execute("""INSERT INTO GetLog (command, vers, scheme, netloc, 
                                               path, params, query, fragment,
                                               username, password, hostname, port)
                           VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
                        (self.command, self.request_version, bits.scheme, bits.netloc,
                         bits.path, bits.params, bits.query, bits.fragment,
                         bits.username, bits.password, bits.hostname, bits.port))
        return super(DBLoggingHandler, self).do_GET()

Кроме того, помните, что запросы могут иметь больше, чем просто командную строку; у них обычно есть заголовки, и у них может быть тело (хотя обычно не для GET). См. headers и rfile для этого. И для информации, которая не является частью HTTP-запроса, но является частью сокет-соединения, или информации о сервере и т. д., для этого тоже есть атрибуты.

person abarnert    schedule 14.08.2014
comment
Это отличный ответ, большое спасибо. Я никогда раньше не пользовался классом, так что мне нужно кое-что изучить. - person metersk; 15.08.2014