2 * Copyright (C) 2011-2012 Juho Vähä-Herttua
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
19 #include "http_request.h"
20 #include "http_parser.h"
22 struct http_request_s
{
24 http_parser_settings parser_settings
;
40 on_url(http_parser
*parser
, const char *at
, size_t length
)
42 http_request_t
*request
= parser
->data
;
43 int urllen
= request
->url
? strlen(request
->url
) : 0;
45 request
->url
= realloc(request
->url
, urllen
+length
+1);
48 request
->url
[urllen
] = '\0';
49 strncat(request
->url
, at
, length
);
54 on_header_field(http_parser
*parser
, const char *at
, size_t length
)
56 http_request_t
*request
= parser
->data
;
58 /* Check if our index is a value */
59 if (request
->headers_index
%2 == 1) {
60 request
->headers_index
++;
63 /* Allocate space for new field-value pair */
64 if (request
->headers_index
== request
->headers_size
) {
65 request
->headers_size
+= 2;
66 request
->headers
= realloc(request
->headers
,
67 request
->headers_size
*sizeof(char*));
68 assert(request
->headers
);
69 request
->headers
[request
->headers_index
] = NULL
;
70 request
->headers
[request
->headers_index
+1] = NULL
;
73 /* Allocate space in the current header string */
74 if (request
->headers
[request
->headers_index
] == NULL
) {
75 request
->headers
[request
->headers_index
] = calloc(1, length
+1);
77 request
->headers
[request
->headers_index
] = realloc(
78 request
->headers
[request
->headers_index
],
79 strlen(request
->headers
[request
->headers_index
])+length
+1
82 assert(request
->headers
[request
->headers_index
]);
84 strncat(request
->headers
[request
->headers_index
], at
, length
);
89 on_header_value(http_parser
*parser
, const char *at
, size_t length
)
91 http_request_t
*request
= parser
->data
;
93 /* Check if our index is a field */
94 if (request
->headers_index
%2 == 0) {
95 request
->headers_index
++;
98 /* Allocate space in the current header string */
99 if (request
->headers
[request
->headers_index
] == NULL
) {
100 request
->headers
[request
->headers_index
] = calloc(1, length
+1);
102 request
->headers
[request
->headers_index
] = realloc(
103 request
->headers
[request
->headers_index
],
104 strlen(request
->headers
[request
->headers_index
])+length
+1
107 assert(request
->headers
[request
->headers_index
]);
109 strncat(request
->headers
[request
->headers_index
], at
, length
);
114 on_body(http_parser
*parser
, const char *at
, size_t length
)
116 http_request_t
*request
= parser
->data
;
118 request
->data
= realloc(request
->data
, request
->datalen
+length
);
119 assert(request
->data
);
121 memcpy(request
->data
+request
->datalen
, at
, length
);
122 request
->datalen
+= length
;
127 on_message_complete(http_parser
*parser
)
129 http_request_t
*request
= parser
->data
;
131 request
->method
= http_method_str(request
->parser
.method
);
132 request
->complete
= 1;
137 http_request_init(int numerichost
)
139 http_request_t
*request
;
141 request
= calloc(1, sizeof(http_request_t
));
145 http_parser_init(&request
->parser
, HTTP_REQUEST
, !!numerichost
);
146 request
->parser
.data
= request
;
148 request
->parser_settings
.on_url
= &on_url
;
149 request
->parser_settings
.on_header_field
= &on_header_field
;
150 request
->parser_settings
.on_header_value
= &on_header_value
;
151 request
->parser_settings
.on_body
= &on_body
;
152 request
->parser_settings
.on_message_complete
= &on_message_complete
;
158 http_request_destroy(http_request_t
*request
)
164 for (i
=0; i
<request
->headers_size
; i
++) {
165 free(request
->headers
[i
]);
167 free(request
->headers
);
174 http_request_add_data(http_request_t
*request
, const char *data
, int datalen
)
180 ret
= http_parser_execute(&request
->parser
,
181 &request
->parser_settings
,
187 http_request_is_complete(http_request_t
*request
)
190 return request
->complete
;
194 http_request_has_error(http_request_t
*request
)
197 return (HTTP_PARSER_ERRNO(&request
->parser
) != HPE_OK
);
201 http_request_get_error_name(http_request_t
*request
)
204 return http_errno_name(HTTP_PARSER_ERRNO(&request
->parser
));
208 http_request_get_error_description(http_request_t
*request
)
211 return http_errno_description(HTTP_PARSER_ERRNO(&request
->parser
));
215 http_request_get_method(http_request_t
*request
)
218 return request
->method
;
222 http_request_get_url(http_request_t
*request
)
229 http_request_get_header(http_request_t
*request
, const char *name
)
235 for (i
=0; i
<request
->headers_size
; i
+=2) {
236 if (!strcmp(request
->headers
[i
], name
)) {
237 return request
->headers
[i
+1];
244 http_request_get_data(http_request_t
*request
, int *datalen
)
249 *datalen
= request
->datalen
;
251 return request
->data
;