2008-09-17 12 views
18

Cで小型で効率的なWebサーバーを構築することに興味があり、HTTPヘッダーからPOSTメソッドを解析する際に問題がありました。誰かが "投稿された"データから名前と値のペアを取り出すのをどのように処理するかについてアドバイスを持っていますか?HTTPヘッダーの解析

POST /test HTTP/1.1 
Host: test-domain.com:7017 
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-us,en;q=0.5 
Accept-Encoding: gzip,deflate 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Keep-Alive: 300 
Connection: keep-alive 
Referer: http://test-domain.com:7017/index.html 
Cookie: __utma=43166241.217413299.1220726314.1221171690.1221200181.16; __utmz=43166241.1220726314.1.1.utmccn=(direct)|utmcsr=(direct)|utmcmd=(none) 
Cache-Control: max-age=0 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 25 

field1=asfd&field2=a3f3f3 
// ^-this 

私は一番下の行全体を取得し、毎回確実に動作するように具体的な方法はありません。私は何でもハードコーディングのファンではありません。

答えて

19

改行改行やより具体的には\ r \ n \ r \ nを検索することで名前と値のペアを取得できます(この後、メッセージの本文が開始されます)。

次に、リストを&で分割し、返された各文字列を=の名前/値の対で分割するだけです。

HTTP 1.1 RFCを参照してください。

+0

ああ、ありがとう。私は、名前と値のペアの文字列の直前に余分なスペースがあることに気づいたが、2と2を一緒に置かなかった。 –

+2

@rofly:2つと2つを計算しないでください。ちょうど標準(RFC 2616)を読んでください。 4.1節にあります。 – bortzmeyer

+2

「\ n \ n」や「\ n \ r \ n」などのヘッダーの「面白い」部分を使用するクライアントに準拠していないクライアントがあることにご注意ください。 – Wade

2

空白行が表示されるまで、ストリームをヘッダーとして解析する必要があります。残りはPOSTデータです。

投稿データ用の小さなパーサーを作成する必要があります。 Cライブラリルーチンを使って、index、strtok、およびsscanfのような素早く汚い何かを行うことができます。あなたが "small"の定義にそれに余裕があるならば、正規表現ライブラリやフレックスやバイソンを使ってもっと精巧なことをすることができます。

少なくとも、私はこの種の答えがあなたの質問だと思います。

4

ヘッダーにContent-Lengthが設定されると、空白行の直後に読み込まれるバイト数がわかります。何らかの理由で(GETまたはPOST)Content-Lengthがヘッダーにない場合は、空白行(crlf)の後には何も読み込まれないことを意味します。

0

IETF RFCにもかかわらず、これ以上の点解はありません。ヘッダーにContent-Length行の後に常に/r/nが追加されていることを認識した場合、dataという名前の変数char*に分離する作業を行うことができます。これが私たちの出発点です。

char *data = "f1=asfd&f2=a3f3f3"; 
char f1[100], 
char f2[100]; 
sscanf(data, "%s&%s", &f1, &f2); // get the field tuples 

char f1_name[50]; 
char f1_data[50]; 
sscanf(f1, "%s=%s", f1_name, f1_data); 

char f2_name[50]; 
char f2_data[50]; 
sscanf(f2, "%s=%s", f2_name, f2_data);