2008-09-17 14 views
18

C로 작고 효율적인 웹 서버를 구축하는 데 새로운 관심이 있었으며 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

@rofly : 두 개와 두 개를 계산하지 말고 그냥 표준 (RFC 2616)을 읽으십시오. 4.1 절에 있습니다. – bortzmeyer

+2

'\ n \ n'또는 '\ n \ r \ n'과 같이 헤더의 "흥미로운"끝 부분을 사용하는 호환되지 않는 클라이언트가 있다는 점에 유의하십시오. – Wade

2

빈 줄이 나타날 때까지 스트림을 헤더로 계속 파싱해야합니다. 나머지는 POST 데이터입니다.

게시물 데이터에 대한 간단한 파서를 작성해야합니다. C 라이브러리 루틴을 사용하여 index, strtok 및 sscanf와 같은 빠르고 더러운 작업을 수행 할 수 있습니다. "작은"것에 대한 정의를위한 공간이 있다면 정규 표현식 라이브러리 또는 flex 및 bison을 사용하여 더 정교한 작업을 수행 할 수 있습니다.

적어도이 종류의 질문에 대한 답변은 생각합니다.

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);