628
技術社區[雲棲]
evhttp處理POST請求的技巧
evhttp處理POST請求的技巧
evhttp是libevent提供的一個輕量級的基於消息驅動的HTTP Server,詳細的資料可以參考libevent的主頁:https://monkey.org/~provos/libevent/ ,本文主要描述如何處理POST請求。
美中不足:evhttp不支持POST?
evhttp在evhttp_request接口中包含一個請求類型type,用來表示HTTP的操作(EVHTTP_REQ_GET,EVHTTP_REQ_POST),但evhttp接口並沒有區分GET和POST操作,我們來看具體的接口實現:
evhttp_request_uri: 解析HTTP請求中的ur;
evhttp_parse_query: 解析名值對;
對於GET操作來說,這兩個函數已經滿足要求,例如:處理如下GET請求:
https://foo.com/?q=test&s=some+thing
evhttp_request_uri: 解析HTTP請求中的ur,得到/?q=test&s=some+thing
evhttp_parse_query: 解析名值對,得到一個evkeyvalq結構,裏麵包含了key/value
的數組.
但如果這個請求是用POST發送的,那麼這兩個函數就不適應了:
evhttp_request_uri: 解析HTTP請求中的ur,得到/
evhttp_parse_query: 解析名值對,q=test&s=some+thing是保存在消息體中而不是uri中,因此解析後是一個空的結構。
除此之外,evhttp並沒有提供接口訪問POST的消息體中的數據。
曲徑通幽:如何處理POST請求?
既然這樣,難道用evhttp就不能使用POST請求了麼?當然不是,隻不過相對GET來說,我們要多費一些周折。下麵就介紹如何在evhttp中處理POST請求。
1. 訪問緩衝區獲取POST消息體數據
evhttp_request結構中包含input_buf結構,input_buffer中的buffer就是存放消息體數據的緩衝區,input_buffer還有一個orig_buffer,實際上和buffer指向的是同一塊內存空間,不知道為什麼這樣設計,但我們用的時候直接用buffer就可以了。
但這裏的buffer並不是全部存放消息體中的數據,buffer的大小是2的N次方,而且總是和實際數據長度最接近的2的N次方,個人猜測evhttp可能使用了slab之類的內存預分配機製,所以這樣處理。
那麼我們如何取到真正的數據呢?其實很簡單:input_buffer有一個offset字段,就是用來指明具體的數據長度的。實際使用的時候,你隻要memcpy一把就可以了。
2. 模擬GET請求參數
如果你的POST請求消息體中存放的是標準的key=value&key=value.....這種格式的數據,你當然可以自己去解析它,但更聰明的辦法是模擬GET請求,再調用evhttp_parse_query函數來幫你解析。
具體步驟如下:
1) 參照“訪問緩衝區獲取POST消息體數據”的指導獲取數據;
2) 將第一步獲取的數據解碼成普通的字符串;
3) evhttp_request_uri解析出uri
4) 組裝成/?q=test&s=some+thing格式的字符串,注意要自己加上問號”?”
5) 調用evhttp_parse_query解析組裝的字符串
需要注意的是:如果你的POST請求消息體中的數據不是這種key=value&key=value.....的格式,那麼就隻能自己處理了,這應該也是evhttp不提供POST請求通用處理的原因吧。
最後更新:2017-04-02 06:51:27