框架头文件:
/************************
* HTTP Parser framework
* 2010-01-11
************************/
#ifndef __SIMPLE_HTTP_H__
#define __SIMPLE_HTTP_H__
#define GET_REQUEST_SIZE 1024
#define HEADER_SIZE 1024
#define CONTENT_SIZE 1024000
// response header
typedef struct {
char content_type[32];
char content_length[32];
} http_response;
// build a GET request
int httpGET(char * sndbuf,
int buflen,
const char * http_version,
const char * http_useragent,
const char * http_host,
const char * http_uri);
// read a response from a socket
// (no reconnection, so your socket must be healthy)
int httpResponse(int fd,
char * content,
int len,
http_response * response);
#endif
GET请求拼装
const char * HTTP_GET_FORMAT =
"GET %s %s/r/n" /
"User-Agent: %s/r/n" /
"Host: %s/r/n" /
"/r/n";
nt httpGET(char * sndbuf,
int buflen,
const char * http_version,
const char * http_useragent,
const char * http_host,
const char * http_uri)
{
if (sndbuf == NULL || buflen <= 0)
{
return -1;
}
return snprintf(sndbuf, buflen, HTTP_GET_FORMAT, http_uri, http_version, http_useragent, http_host);
}
Response解析 -- header 与 Content 切分部分
int httpResponse(int fd, char * content, int len, http_response * response)
{
char header[HEADER_SIZE] = { 0 };
char c;
char line[1024];
int cindex = 0;
// analyze status
int status = 0;
char * contentptr = content;
char * headerptr = header;
char * content_head = NULL;
int readnum = 0;
int content_length = 0;
int content_rest_length = 0;
if (fd < 0 || content == NULL || len <= 0)
{
return -1;
}
if ((readnum = read(fd, header, HEADER_SIZE)) > 0)
{
while ((c = *headerptr) && content_head == NULL)
{
switch (status)
{
case 0: // nothing happend
if (c == '/r')
{
status = 1;
httpParseLine(line, cindex, response); // a whole line
cindex = 0;
memset(line, 0, sizeof(line));
}
else
{
line[cindex++] = c;
}
headerptr ++;
break;
case 1: // a /r appeared
if (c == '/n')
{
status = 2;
headerptr ++;
}
else
{
status = 0;
}
break;
case 2: // a /n followed a /r
if (c == '/r')
{
status = 3;
headerptr ++;
}
else
{
status = 0;
}
break;
case 3: // a /r followed a /r/n pair
if (c == '/n')
{
status = 4;
headerptr ++;
}
else
{
status = 0;
}
break;
case 4: // head tail
content_head = headerptr;
content_length = atoi(response->content_length);
content_rest_length = content_length - (readnum - (headerptr - header));
contentptr = content;
strncpy(content, content_head, readnum - (headerptr - header));
contentptr += readnum - (headerptr - header);
while (content_rest_length > 0)
{
readnum = read(fd, contentptr, content_rest_length);
contentptr += readnum;
content_rest_length -= readnum;
}
break;
}
}
}
return 0;
}
header Parser
// parser item in head
static int httpParseLine(const char * line, int len, http_response * response)
{
char c;
int index = 0;
int status = 0;
if (line == NULL || len == 0 || response == NULL)
{
return -1;
}
while (status != 1)
{
switch (status)
{
case 0: // nothing happened
if (strncmp(line, "Content-Type:", 13) == 0)
{
status = 2;
}
else if (strncmp(line, "Content-Length:", 15) == 0)
{
status = 3;
}
else
{
return -1;
}
break;
case 1: // finished
break;
case 2:
strcpy(response->content_type, line + 13);
status = 1;
break;
case 3:
strcpy(response->content_length, line + 15);
status = 1;
break;
}
}
return 0;
}