我正在玩这个想法,为我正在使用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标准方法。
感谢您的时间。
答案 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
进行调用时