扩展CGIHTTPRequestHandler或BaseHTTPRequestHandler。解析请求的最佳实践

时间:2014-01-15 03:27:57

标签: python parsing

我正在玩这个想法,为我正在使用Python构建的守护进程添加一个集成的HTTP接口。我喜欢这种方法,因为它使整个守护进程代码可移植。(而不是有一个单独的web部分和cli部分)。

一切都很好,但我想知道解析我在do_GET方法中收到的实际请求的最佳做法。

这是我的原型do_GET方法

def do_GET(self):
        str = "OK"
        print self.request
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.send_header("Content-length", len(str))
        self.end_headers()
        self.wfile.write(str)

request属性在收到请求时包含以下字符串

  

127.0.0.1 - - [15 / Jan / 2014 10:21:23]“GET /”200 -

是否有可用于解析此字符串的标准库?我需要编写的自定义解析器,我相信首先使用-作为分隔符对字符串进行标记,然后处理第3个元素,使用某种正则表达式匹配[([^\]]+)]请求日期和{{1}用于请求路径。

我担心编写自定义解析器,因为我可能遇到的所有异常。所以我正在询问任何用于解析此问题的python标准方法。

感谢您的时间。

3 个答案:

答案 0 :(得分:2)

如果你能找到一个解析这些字符串的实体库,那显然是你最好的选择。

如果您想尝试使用pyparsing的解决方案失败,这可能会帮助您入门:

import re
from pyparsing import Combine, Literal, Regex, White, Word
from pyparsing import alphanums, alphas, nums

data = '127.0.0.1 - - [15/Jan/2014 10:21:23] "GET /" 200 -'

ip_octet = Word(nums, min=1, max=3)
ip_sep = Literal('.')
ip = Combine(ip_octet + ip_sep
             + ip_octet + ip_sep
             + ip_octet + ip_sep
             + ip_octet)

day = Word(nums, min=1, max=2)
month = Word(alphas, exact=3)
year = Word(nums, exact=4)
date_sep = Literal('/')
date = Combine(day + date_sep
               + month + date_sep
               + year)
hms = Word(nums, min=1, max=2)
time_sep = Literal(':')
time = Combine(hms + time_sep
               + hms + time_sep
               + hms)
datetime = Literal('[').suppress() + date + time + Literal(']').suppress()

method = Word(alphas) # GET, etc
# path characters per RFC 1738 / <http://stackoverflow.com/a/1856809/1535629>
path = Word(alphanums + "$-_.+!*'(),/%")
req_enclosure = Literal('"').suppress()
req = req_enclosure + method + path + req_enclosure

code = Word(nums, exact=3) # HTTP status code

nodash = Literal('-').suppress()
parser = ip + nodash + nodash + datetime + req + code + nodash

result = parser.parseString(data)
print(result)

结果:

['127.0.0.1', '15/Jan/2014', '10:21:23', 'GET', '/', '200']

在我看来,这比使用re更加冗长,但是更具可读性和可维护性。


此外,如果您愿意,可以pyparsing中使用正则表达式,如下所示:

import re
from pyparsing import Regex

data = '127.0.0.1'

ip_re = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
ip = Regex(ip_re)

result = ip.parseString(data)
print(result)

结果:

['127.0.0.1']

这使您可以选择以最方便的方式混合和匹配正则表达式和pyparsing功能。

答案 1 :(得分:0)

http://deron.meranda.us/python/httpheader/就是这样一个可以帮助你解析HTTP标头的库。

答案 2 :(得分:0)

好的,经过进一步调查,我发现CGIHTTPRequestHandler有一个名为path的属性名称。因此,如下更改do_GET方法可以为我提供所需的结果

def do_GET(self):

        str = "OK"

        print self.path

        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.send_header("Content-length", len(str))
        self.end_headers()
        self.wfile.write(str)

输出

/send/message
使用GET /send/message

进行调用时