HTTP协议框架 - 构建最简单的 GET 请求拼装和 Response 解析

头文件:

1 /************************
2 * HTTP Parser framework
3 * 2010-01-11
4 ************************/
5
6 #ifndef __SIMPLE_HTTP_H__
7  #define __SIMPLE_HTTP_H__
8
9  #define GET_REQUEST_SIZE 1024
10
11  #define HEADER_SIZE 1024
12  #define CONTENT_SIZE 1024000
13
14  // response header
15  typedef struct {
16 char content_type[32];
17 char content_length[32];
18 } http_response;
19
20 // build a GET request
21 int httpGET(char * sndbuf,
22 int buflen,
23 const char * http_version,
24 const char * http_useragent,
25 const char * http_host,
26 const char * http_uri);
27
28 // read a response from a socket
29 // (no reconnection, so your socket must be healthy)
30 int httpResponse(int fd,
31 char * content,
32 int len,
33 http_response * response);
34
35 #endif

 

GET请求拼装格式:

1 const char * HTTP_GET_FORMAT =
2 "GET %s %s\r\n" \
3 "User-Agent: %s\r\n" \
4 "Host: %s\r\n" \
5 "\r\n";

 

拼装部分:

1 int httpGET(char * sndbuf,
2 int buflen,
3 const char * http_version,
4 const char * http_useragent,
5 const char * http_host,
6 const char * http_uri)
7 {
8 if (sndbuf == NULL || buflen <= 0)
9 {
10 return -1;
11 }
12
13 return snprintf(sndbuf, buflen, HTTP_GET_FORMAT, http_uri, http_version, http_useragent, http_host);
14 }

 

Response解析 -- header 与 Content 切分部分

代码
1 int httpResponse(int fd, char * content, int len, http_response * response)
2 {
3 char header[HEADER_SIZE] = { 0 };
4
5 char c;
6 char line[1024];
7 int cindex = 0;
8
9 // analyze status
10 int status = 0;
11
12 char * contentptr = content;
13 char * headerptr = header;
14 char * content_head = NULL;
15
16 int readnum = 0;
17 int content_length = 0;
18 int content_rest_length = 0;
19
20 if (fd < 0 || content == NULL || len <= 0)
21 {
22 return -1;
23 }
24
25 if ((readnum = read(fd, header, HEADER_SIZE)) > 0)
26 {
27 while ((c = *headerptr) && content_head == NULL)
28 {
29 switch (status)
30 {
31 case 0: // nothing happend
32 if (c == '\r')
33 {
34 status = 1;
35
36 httpParseLine(line, cindex, response); // a whole line
37
38 cindex = 0;
39 memset(line, 0, sizeof(line));
40 }
41 else
42 {
43 line[cindex++] = c;
44 }
45 headerptr ++;
46 break;
47 case 1: // a \r appeared
48 if (c == '\n')
49 {
50 status = 2;
51 headerptr ++;
52 }
53 else
54 {
55 status = 0;
56 }
57 break;
58 case 2: // a \n followed a \r
59 if (c == '\r')
60 {
61 status = 3;
62 headerptr ++;
63 }
64 else
65 {
66 status = 0;
67 }
68 break;
69 case 3: // a \r followed a \r\n pair
70 if (c == '\n')
71 {
72 status = 4;
73 headerptr ++;
74 }
75 else
76 {
77 status = 0;
78 }
79 break;
80 case 4: // head tail
81 content_head = headerptr;
82 content_length = atoi(response->content_length);
83 content_rest_length = content_length - (readnum - (headerptr - header));
84 contentptr = content;
85 strncpy(content, content_head, readnum - (headerptr - header));
86 contentptr += readnum - (headerptr - header);
87 while (content_rest_length > 0)
88 {
89 readnum = read(fd, contentptr, content_rest_length);
90 contentptr += readnum;
91 content_rest_length -= readnum;
92 }
93 break;
94 }
95 }
96 }
97
98 return 0;
99 }

 

header Parser

代码
1 // parser item in head
2 static int httpParseLine(const char * line, int len, http_response * response)
3 {
4 char c;
5 int index = 0;
6 int status = 0;
7
8 if (line == NULL || len == 0 || response == NULL)
9 {
10 return -1;
11 }
12
13 while (status != 1)
14 {
15 switch (status)
16 {
17 case 0: // nothing happened
18 if (strncmp(line, "Content-Type:", 13) == 0)
19 {
20 status = 2;
21 }
22 else if (strncmp(line, "Content-Length:", 15) == 0)
23 {
24 status = 3;
25 }
26 else
27 {
28 return -1;
29 }
30 break;
31 case 1: // finished
32 break;
33 case 2:
34 strcpy(response->content_type, line + 13);
35 status = 1;
36 break;
37 case 3:
38 strcpy(response->content_length, line + 15);
39 status = 1;
40 break;
41 }
42 }
43
44 return 0;
45 }

 

posted @ 2010-02-05 13:40  boymgl  阅读(1053)  评论(0编辑  收藏  举报