summaryrefslogtreecommitdiff
path: root/src/HTTP_Parser.c
diff options
context:
space:
mode:
author刘学利 <[email protected]>2022-06-01 08:02:07 +0000
committer刘学利 <[email protected]>2022-06-01 08:02:07 +0000
commit274614cde4d166fb1209e51432609377f48ee7e8 (patch)
treec8efb60d425cc1f55cc8bc3efdee6f8605f76c09 /src/HTTP_Parser.c
parentb672af8e7e48ea426410497d7b0b22ca6767a879 (diff)
TSG-9128, TSG-9650: 提供解析HTTP头部字段的函数http_field_parserv2.0.10
Diffstat (limited to 'src/HTTP_Parser.c')
-rw-r--r--src/HTTP_Parser.c279
1 files changed, 205 insertions, 74 deletions
diff --git a/src/HTTP_Parser.c b/src/HTTP_Parser.c
index 9a0e61b..444fd06 100644
--- a/src/HTTP_Parser.c
+++ b/src/HTTP_Parser.c
@@ -13,48 +13,100 @@
extern const char* g_http_method[];
-typedef struct host_parser_t
+struct http_header_field
+{
+ int field_flag;
+ int length;
+ char *value;
+};
+
+struct http_header_parse
{
- char* host_value;
char is_http_flag;
- char get_host_flag;
- char host_field_flag;
- char host_value_flag;
- uint32 host_valuelen;
-}host_parser;
+ char pad[7];
+ long long http_field_flag;
+ struct http_header_field host;
+ struct http_header_field uri;
+ struct http_header_field url;
+};
+
int http_parser_callback_on_headers_field(struct http_parser * parser, const char * at, size_t length)
{
- if(((host_parser*)(parser->data))->get_host_flag==0 || ((host_parser*)(parser->data))->host_field_flag==1) return 0;
- if(0==strncasecmp(at, "host",strlen("host")))
+ if(at==NULL || length<=0 || parser==NULL || parser->data==NULL)
{
- ((host_parser*)(parser->data))->host_field_flag = 1;
+ return 0;
}
+
+ struct http_header_parse *header_parser=(struct http_header_parse *)(parser->data);
+ header_parser->is_http_flag=1;
+
+ if((header_parser->host.field_flag==0) && (length==4) && (0==strncasecmp(at, "host", 4)))
+ {
+ header_parser->host.field_flag=1;
+ header_parser->http_field_flag=HTTP_HOST;
+ }
+
return 0;
}
int http_parser_callback_on_headers_value(struct http_parser * parser, const char * at, size_t length)
-{
- if(((host_parser*)(parser->data))->get_host_flag==0 || ((host_parser*)(parser->data))->host_field_flag==0 || ((host_parser*)(parser->data))->host_value_flag==1) return 0;
- if(0<length)
+{
+ if(at==NULL || length<=0 || parser==NULL || parser->data==NULL)
+ {
+ return 0;
+ }
+
+ struct http_header_parse *header_parser=(struct http_header_parse *)(parser->data);
+ header_parser->is_http_flag=1;
+
+ switch(header_parser->http_field_flag)
{
- ((host_parser*)(parser->data))->host_value = (char*)malloc(length);
- memcpy(((host_parser*)(parser->data))->host_value, at, length);
- ((host_parser*)(parser->data))->host_valuelen = length;
- ((host_parser*)(parser->data))->host_value_flag = 1;
+ case HTTP_HOST:
+ header_parser->host.value=(char*)malloc(length);
+ memcpy(header_parser->host.value, at, length);
+ header_parser->host.length=length;
+ header_parser->http_field_flag=HTTP_INTEREST_KEY;
+ break;
+ default:
+ break;
}
+
return 0;
}
int http_parser_callback_on_url(struct http_parser * parser, const char * at, size_t length)
{
- ((host_parser*)(parser->data))->is_http_flag = 1;
+ if(at==NULL || length<=0 || parser==NULL || parser->data==NULL)
+ {
+ return 0;
+ }
+
+ struct http_header_parse *header_parser=(struct http_header_parse *)(parser->data);
+ header_parser->is_http_flag=1;
+
+ if(header_parser->uri.field_flag==0)
+ {
+ header_parser->uri.field_flag=1;
+ header_parser->uri.value=(char*)malloc(length);
+ memcpy(header_parser->uri.value, at, length);
+ header_parser->uri.length=length;
+ header_parser->http_field_flag=HTTP_INTEREST_KEY;
+ }
+
return 0;
}
int http_parser_callback_on_status(struct http_parser * parser, const char * at, size_t length)
{
- ((host_parser*)(parser->data))->is_http_flag = 1;
+ if(at==NULL || length<=0 || parser==NULL || parser->data==NULL)
+ {
+ return 0;
+ }
+
+ struct http_header_parse *header_parser=(struct http_header_parse *)(parser->data);
+ header_parser->is_http_flag=1;
+
return 0;
}
@@ -72,7 +124,7 @@ static http_parser_settings http_setting =
.on_chunk_complete = NULL
};
-int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host)
+void *http_field_parser(const char* buf, uint32 buflen, int http_dir)
{
//bufǰ��Ŀո����ɾ������
uint32 offset = 0;
@@ -85,24 +137,17 @@ int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host)
uint32 new_pbuflen = 0;
uchar method = HTTP_METHOD_UNKNOWN;
int method_idx = 1, new_flags=0;
-
+ struct http_parser http_parse={0};
+
if(pbuflen<4) //g_http_method min bytes=3; pbuflen_temp=pbuflen
{
- return -1;
+ return NULL;
}
-
- //printf("buf=====================================================\n");
- //printf("%s\n", buf);
-
- // Ϊ�ṹ�������ڴ�
- http_parser *parser = (http_parser*)calloc(1, sizeof(http_parser));
- host_parser* host_field = (host_parser*)calloc(1, sizeof(host_parser));
- int rec = -1;
// ��ʼ��������
if(http_dir==DIR_C2S)
{
- http_parser_init(parser, HTTP_REQUEST);
+ http_parser_init(&http_parse, HTTP_REQUEST);
/*�����⵽method�����ƶ�һ���ո񣬲���'/',Ҳ����"http://"�����Զ�����һ��'/'*/
if(buflen>HTTP_START_FLAGS_LEN+strlen("http://"))
{
@@ -134,64 +179,150 @@ int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host)
}
else
{
- http_parser_init(parser, HTTP_RESPONSE);
- }
- parser->data = (void*)host_field;
-
- //��ȡhost����
- if(host!=NULL)
- {
- ((host_parser*)(parser->data))->get_host_flag = 1;
+ http_parser_init(&http_parse, HTTP_RESPONSE);
}
- size_t parsed=0;
+ struct http_header_parse *http_header=calloc(1, sizeof(struct http_header_parse));
+ http_parse.data=(void*)(http_header);
+
//ִ�н�������
if(new_flags==0)
{
- parsed=http_parser_execute(parser, &http_setting, pbuf, (size_t)pbuflen);
+ http_parser_execute(&http_parse, &http_setting, pbuf, (size_t)pbuflen);
}
else
{
- parsed=http_parser_execute(parser, &http_setting, new_pbuf, (size_t)new_pbuflen);
+ http_parser_execute(&http_parse, &http_setting, new_pbuf, (size_t)new_pbuflen);
}
- //printf("buflen: %d; parsed: %d\n", pbuflen, parsed);
- if(((host_parser*)(parser->data))->is_http_flag == 1)
+
+ if(NULL!=new_pbuf)
+ {
+ free(new_pbuf);
+ new_pbuf = NULL;
+ }
+
+ if(http_header->is_http_flag==0)
{
- rec = 0;
- if(((host_parser*)(parser->data))->get_host_flag == 1)
- {
- if(0<host_field->host_valuelen)
- {
- rec = host_field->host_valuelen;
- *host = memcasemem(pbuf, pbuflen, (const char*)host_field->host_value, host_field->host_valuelen);
- }
- }
- }
- else
+ free(http_header);
+ http_header=NULL;
+ return NULL;
+ }
+
+ if(http_header->host.field_flag==1 && http_header->host.length>0 && http_header->host.value!=NULL)
{
- rec = -1;
+ char *p_host=memcasemem(pbuf, pbuflen, (const char*)http_header->host.value, http_header->host.length);
+ free(http_header->host.value);
+ http_header->host.value=p_host;
}
+
+ return (void *)(http_header);
+}
- if(NULL!=host_field)
+void http_free_filed_result(void *result)
+{
+ if(result==NULL)
{
- if(NULL!=host_field->host_value)
- {
- free(host_field->host_value);
- host_field->host_value = NULL;
- }
- free(host_field);
- host_field = NULL;
- }
- if(NULL!=parser)
- {
- free(parser);
- parser = NULL;
+ return ;
}
- if(NULL!=new_pbuf)
- {
- free(new_pbuf);
- new_pbuf = NULL;
+
+ struct http_header_parse *http_header=(struct http_header_parse *)result;
+ if(http_header->uri.value!=NULL)
+ {
+ free(http_header->uri.value);
+ http_header->uri.value=NULL;
+ }
+
+ if(http_header->url.value!=NULL)
+ {
+ free(http_header->url.value);
+ http_header->url.value=NULL;
}
- return rec;
+
+ free(result);
+ result=NULL;
+}
+
+int http_get_filed_result(void *result, long long field_flag, char **field_value)
+{
+ if(result==NULL)
+ {
+ return 0;
+ }
+
+ struct http_header_parse *http_header=(struct http_header_parse *)result;
+
+ switch(field_flag)
+ {
+ case HTTP_HOST:
+ if(http_header->host.field_flag==0 || http_header->host.value==NULL || http_header->host.length<=0)
+ {
+ break;
+ }
+ *field_value=http_header->host.value;
+ return http_header->host.length;
+ case HTTP_MESSAGE_URL:
+ if(http_header->host.field_flag==0 || http_header->host.value==NULL || http_header->host.length<=0)
+ {
+ break;
+ }
+
+ http_header->url.length=http_header->host.length;
+ http_header->url.value=malloc(http_header->url.length);
+ memcpy(http_header->url.value, http_header->host.value, http_header->host.length);
+
+ if(http_header->uri.field_flag==0 || http_header->uri.value==NULL || http_header->uri.length<=0)
+ {
+ http_header->url.value=realloc(http_header->url.value, http_header->url.length+1);
+ http_header->url.value[http_header->url.length]='/';
+ http_header->url.length+=1;
+ }
+ else
+ {
+ if(http_header->uri.value[0]=='/')
+ {
+ http_header->url.value=realloc(http_header->url.value, http_header->url.length+http_header->uri.length);
+ }
+ else
+ {
+ http_header->url.value=realloc(http_header->url.value, http_header->url.length+http_header->uri.length+1);
+ http_header->url.value[http_header->url.length]='/';
+ http_header->url.length+=1;
+ }
+
+ memcpy(http_header->url.value+http_header->url.length, http_header->uri.value, http_header->uri.length);
+ http_header->url.length+=http_header->uri.length;
+ }
+
+ *field_value=http_header->url.value;
+ return http_header->url.length;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int http_host_parser(const char* buf, uint32 buflen, int http_dir, char** host)
+{
+ struct http_header_parse *http_header=(struct http_header_parse *)http_field_parser(buf, buflen, http_dir);
+ if(http_header==NULL)
+ {
+ return -1;
+ }
+
+ int length=0;
+
+ if(http_header->is_http_flag==1)
+ {
+ if(http_header->host.field_flag==1 && http_header->host.length>0 && http_header->host.value!=NULL)
+ {
+ *host=http_header->host.value;
+ length=http_header->host.length;
+ }
+ }
+
+ http_free_filed_result((void *)http_header); //no need free host, *host=buf+N
+
+ return length;
}