2014-01-15 64 views
0

我在爲使用Python構建的守護進程添加一個集成的HTTP接口的想法。我喜歡這種方法,因爲它使整個守護程序代碼變得可移植(而不是具有單獨的Web部分和cli部分)。擴展CGIHTTPRequestHandler或BaseHTTPRequestHandler。解析請求的最佳實踐

一切都很好,但我想知道最佳實踐來分析我在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 /月/ 2014 10點21分: 23] 「GET /」 200 -

有沒有我可以用它來解析這個字符串標準庫?一個自定義解析器,我需要寫我相信首先標記字符串使用-作爲分隔符,然後處理第三個元素與某種正則表達式匹配請求日期[([^\]]+)]和請求路徑"[[^\"]+"

我很擔心編寫自定義分析器,因爲我可能遇到的所有異常。所以我正在查詢任何用於解析這個的python標準方法。

謝謝你的時間。

+1

稱爲如果你發現自己無法找到能夠分析這些字符串庫,可以考慮使用['pyparsing'](http://pyparsing.wikispaces.com/)而不是使用正則表達式來提高健壯性。 – senshin

+0

@senshin好的謝謝你的提示,我會檢查。 – DevZer0

回答

0

http://deron.meranda.us/python/httpheader/是一個這樣的庫,可以幫助你解析HTTP頭。

+0

我不相信這是我正在尋找的。我遇到的請求字符串沒有任何頭信息,當您通過標準的http服務器提供python腳本時,您建議的庫似乎用於頭解析。 – DevZer0

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功能。

+0

+1爲您提供pyparsing更詳細的答案的努力 – DevZer0

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