2 * @file http_request.cpp
3 * @brief module of HTTP Request
4 * @brief HTTP Request parser
6 * Copyright (C) 2009 NTT COMWARE Corporation.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 **********************************************************************/
25 #include "http_request.h"
28 * HTTP Request constructor.
30 http_request::http_request()
32 /*-------- DEBUG LOG --------*/
33 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
34 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 20,
35 "in/out_function : Constructor http_request::http_request(void)");
37 /*------ DEBUG LOG END ------*/
41 * HTTP Request constructor.
42 * Parse HTTP request header.
44 * @param[in] header full http request header string
46 http_request::http_request(std::string header)
48 /*-------- DEBUG LOG --------*/
49 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
50 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 21,
51 "in/out_function : Constructor http_request::http_request(std::string header) : "
52 "header(%s)", header.c_str());
54 /*------ DEBUG LOG END ------*/
59 * HTTP Request destructor.
61 http_request::~http_request()
63 /*-------- DEBUG LOG --------*/
64 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
65 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 22,
66 "in/out_function : Destructor http_request::~http_request(void)");
68 /*------ DEBUG LOG END ------*/
72 * Get method function.
76 std::string http_request::method() const
78 /*-------- DEBUG LOG --------*/
79 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
80 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 23,
81 "in_function : std::string http_request::method(void)");
82 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 24,
83 "out_function : std::string http_request::method(void) : "
84 "return(%s)", this->_method.c_str());
86 /*------ DEBUG LOG END ------*/
92 * Set method function.
93 * Set new method and return old method.
95 * @param[in] method new method
98 std::string http_request::method(std::string _method)
100 /*-------- DEBUG LOG --------*/
101 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
102 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 25,
103 "in_function : std::string http_request::method(std::string _method) : "
104 "_method(%s)", _method.c_str());
106 /*------ DEBUG LOG END ------*/
108 std::string ret = this->_method;
109 this->_method = _method;
110 this->modified = true;
112 /*-------- DEBUG LOG --------*/
113 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
114 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 26,
115 "out_function : std::string http_request::method(std::string _method) : "
116 "return(%s)", ret.c_str());
118 /*------ DEBUG LOG END ------*/
124 * Get request URI function.
126 * @return request URI
128 std::string http_request::request_uri() const
130 /*-------- DEBUG LOG --------*/
131 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
132 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 27,
133 "in_function : std::string http_request::request_uri(void)");
134 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 28,
135 "out_function : std::string http_request::request_uri(void) : "
136 "return(%s)", this->_request_uri.c_str());
138 /*------ DEBUG LOG END ------*/
140 return this->_request_uri;
144 * Set request URI function.
145 * Set new request URI and return old request URI.
147 * @param[in] _request_uri new request URI
148 * @return old request URI
150 std::string http_request::request_uri(std::string _request_uri)
152 /*-------- DEBUG LOG --------*/
153 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
154 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 29,
155 "in_function : std::string http_request::request_uri(std::string _request_uri) : "
156 "_request_uri(%s)", _request_uri.c_str());
158 /*------ DEBUG LOG END ------*/
160 std::string ret = this->_request_uri;
161 this->_request_uri = _request_uri;
162 this->modified = true;
164 /*-------- DEBUG LOG --------*/
165 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
166 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 30,
167 "out_function : std::string http_request::_request_uri(std::string _request_uri) : "
168 "return(%s)", ret.c_str());
170 /*------ DEBUG LOG END ------*/
176 * Get HTTP version function.
178 * @return HTTP version
180 std::string http_request::http_version() const
182 /*-------- DEBUG LOG --------*/
183 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
184 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 31,
185 "in_function : std::string http_request::http_version(void)");
186 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 32,
187 "out_function : std::string http_request::http_version(void) : "
188 "return(%s)", this->_http_version.c_str());
190 /*------ DEBUG LOG END ------*/
192 return this->_http_version;
196 * Set HTTP version function.
197 * Set new HTTP version and return old HTTP version.
199 * @param[in] _http_version new HTTP version
200 * @return old HTTP version
202 std::string http_request::http_version(std::string _http_version)
204 /*-------- DEBUG LOG --------*/
205 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
206 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 33,
207 "in_function : std::string http_request::http_version(std::string _http_version) : "
208 "_http_version(%s)", _http_version.c_str());
210 /*------ DEBUG LOG END ------*/
212 std::string ret = this->_http_version;
213 this->_http_version = _http_version;
214 this->modified = true;
216 /*-------- DEBUG LOG --------*/
217 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
218 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 34,
219 "out_function : std::string http_request::http_version(std::string _http_version) : "
220 "return(%s)", ret.c_str());
222 /*------ DEBUG LOG END ------*/
228 * Get request line function.
230 * @return request line
232 std::string http_request::request_line() const
234 /*-------- DEBUG LOG --------*/
235 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
236 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 35,
237 "in_function : std::string http_request::request_line(void)");
239 /*------ DEBUG LOG END ------*/
241 std::string ret = this->method() + " " + this->request_uri() + " " + this->http_version() + "\r\n";
243 /*-------- DEBUG LOG --------*/
244 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
245 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 36,
246 "out_function : std::string http_request::request_line(void) : "
247 "return(%s)", ret.c_str());
249 /*------ DEBUG LOG END ------*/
255 * Get full HTTP request function.
257 * @return HTTP request
259 std::string http_request::as_string()
261 /*-------- DEBUG LOG --------*/
262 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
263 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 37,
264 "in_function : std::string http_request::as_string(void)");
266 /*------ DEBUG LOG END ------*/
271 /*-------- DEBUG LOG --------*/
272 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
273 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 38,
274 "out_function : std::string http_request::as_string(void) : "
275 "return(%s)", this->raw_message.c_str());
277 /*------ DEBUG LOG END ------*/
279 return this->raw_message;
283 * Parse HTTP request header function.
285 * @param[in] request full HTTP request header
287 void http_request::parse(std::string request)
289 /*-------- DEBUG LOG --------*/
290 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
291 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 39,
292 "in_function : void http_request::parse(std::string request) : "
293 "request(%s)", request.c_str());
295 /*------ DEBUG LOG END ------*/
298 this->raw_message = request;
301 HTTP_REQUEST_POSITION pos = REQUEST_METHOD;
306 * CHAR : US-ASCII(0-127)
309 * ALPHA : UPALPHA | LOALPHA
311 * HEXDIG : A-F | a-f | DIGIT
313 * HT : Horizontal Tab(9)
314 * CR : Carriage Return(13)
316 * CTL : ConTLol char(0-31,127)
317 * LWS : [CRLF] 1*(SP|HT)
318 * separators : ()<>@,;:\"/[]?={} and SP, HT
319 * token : 1*(CHAR not CTL, separators)
321 std::string::iterator ptr = request.begin();
322 std::string::iterator end = request.end();
323 std::string::iterator start = ptr;
324 std::pair<std::string, std::string> field_pair;
330 * METHOD SP REQUEST-URI SP HTTP-VERSION CRLF
336 if (*ptr == ' ') { // METHOD end with SP
337 this->_method.assign(start, ptr);
338 pos = REQUEST_METHOD_SP;
339 } else if (!isalpha(*ptr) && !isdigit(*ptr)) { // XXX not enough
340 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 10,
341 "Parse error: Invalid request method.(%c)", *ptr);
346 * REQUEST-URI : * | absolute-URI | path-absolute | authority
349 * absolute-URI : scheme ":" hier-part [ "?" query ]
350 * path-absolute : "/" [ segment-nz *( "/" segment ) ]
351 * authority : [ userinfo "@" ] host [ ":" port ]
352 * scheme : ALPHA *( ALPHA | DIGIT | "+" | "-" | "." )
353 * hier-part : "//" authority path-abempty
357 * query : *( pchar | "/" | "?" )
358 * path-abempty : *( "/" segment )
359 * path-rootless : segment-nz *( "/" segment )
360 * path-empty : no char
361 * segment-nz : 1*pchar
363 * userinfo : *( unreserved | pct-encoded | sub-delims | ":" )
364 * host : IP-literal | IPv4address | reg-name
366 * unreserved : ALPHA | DIGIT | "-" | "." | "_" | "~"
367 * pct-encoded : "%" HEXDIG HEXDIG
368 * sub-delims : !$&'()*+,;=
369 * pchar : unreserved | pct-encoded | subdelims | ":" | "@"
370 * IP-literal : "[" ( IPv6address | IPvFuture ) "]"
371 * IPvFuture : "v" 1*HEXDIG "." 1*( unreserved | sub-delims | ":" )
372 * IPv6address : 6( h16 ":" ) ls32
373 * / "::" 5( h16 ":" ) ls32
374 * / [ h16 ] "::" 4( h16 ":" ) ls32
375 * / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
376 * / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
377 * / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
378 * / [ *4( h16 ":" ) h16 ] "::" ls32
379 * / [ *5( h16 ":" ) h16 ] "::" h16
380 * / [ *6( h16 ":" ) h16 ] "::"
382 * ls32 : ( h16 ":" h16 ) | IPv4address
383 * IPv4address : dec-octet "." dec-octet "." dec-octet "." dec-octet
385 * reg-name : *( unreserved | pct-encoded | sub-delims )
387 case REQUEST_METHOD_SP:
390 if (*ptr == '/' || isalpha(*ptr) || isdigit(*ptr) || *ptr == '-' ||
391 *ptr == '.' || *ptr == '_' || *ptr == '~' || *ptr == ':' ||
392 *ptr == '@' || *ptr == '!' || *ptr == '$' || *ptr == '&' ||
393 *ptr == '(' || *ptr == ')' || *ptr == '*' || *ptr == '+' ||
394 *ptr == ',' || *ptr == ';' || *ptr == '=' || *ptr == '%') {
395 pos = REQUEST_REQUEST_URI;
398 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 11,
399 "Parse error: Invalid request-uri.(%c)", *ptr);
404 case REQUEST_REQUEST_URI:
405 if (*ptr == ' ') { // Request-URI end with SP
406 this->_request_uri.assign(start, ptr);
407 pos = REQUEST_REQUEST_URI_SP;
408 } else if (!isalpha(*ptr) && !isdigit(*ptr) && *ptr != '/' && // XXX not enough?
409 *ptr != '.' && *ptr != '=' && *ptr != '%' && *ptr != '?' &&
410 *ptr != '&' && *ptr != '+' && *ptr != '~' && *ptr != ',' &&
411 *ptr != '@' && *ptr != '!' && *ptr != '$' && *ptr != '-' &&
412 *ptr != '(' && *ptr != ')' && *ptr != '*' && *ptr != '_' &&
413 *ptr != ':' && *ptr != ';') {
414 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 12,
415 "Parse error: Invalid request-uri.(%c)", *ptr);
421 * HTTP-VERSION : "HTTP" "/" 1*DIGIT "." 1*DIGIT
423 case REQUEST_REQUEST_URI_SP:
424 // HTTP-VERSION start
426 pos = REQUEST_HTTP_VERSION_H;
429 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 13,
430 "Parse error: Invalid http-version.(%c)", *ptr);
435 case REQUEST_HTTP_VERSION_H:
438 pos = REQUEST_HTTP_VERSION_T1;
440 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 14,
441 "Parse error: Invalid http-version.(%c)", *ptr);
446 case REQUEST_HTTP_VERSION_T1:
449 pos = REQUEST_HTTP_VERSION_T2;
451 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 15,
452 "Parse error: Invalid http-version.(%c)", *ptr);
457 case REQUEST_HTTP_VERSION_T2:
460 pos = REQUEST_HTTP_VERSION_P;
462 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 16,
463 "Parse error: Invalid http-version.(%c)", *ptr);
468 case REQUEST_HTTP_VERSION_P:
471 pos = REQUEST_HTTP_VERSION_SLASH;
473 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 17,
474 "Parse error: Invalid http-version.(%c)", *ptr);
479 case REQUEST_HTTP_VERSION_SLASH:
480 // HTTP-VERSION Mejor number
482 pos = REQUEST_HTTP_VERSION_MAJOR;
484 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 18,
485 "Parse error: Invalid http-version.(%c)", *ptr);
490 case REQUEST_HTTP_VERSION_MAJOR:
491 // HTTP-VERSION next dot
493 pos = REQUEST_HTTP_VERSION_DOT;
494 } else if (!isdigit(*ptr)) {
495 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 19,
496 "Parse error: Invalid http-version.(%c)", *ptr);
501 case REQUEST_HTTP_VERSION_DOT:
502 // HTTP-VERSION Minor number
504 pos = REQUEST_HTTP_VERSION_MINOR;
506 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 20,
507 "Parse error: Invalid http-version.(%c)", *ptr);
512 case REQUEST_HTTP_VERSION_MINOR:
513 // HTTP-VERSION end with CR
516 this->_http_version.assign(start, ptr);
517 } else if (!isdigit(*ptr)) {
518 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 21,
519 "Parse error: Invalid http-version.(%c)", *ptr);
528 http_message::parse(std::string(ptr + 1, end));
530 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 22,
531 "Parse error: No LF.(%c)", *ptr);
536 if (pos == REQUEST_LF)
542 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT_HTTP, 23,
543 "Exception occured by parsing HTTP request.");
546 /*-------- DEBUG LOG --------*/
547 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
548 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 40,
549 "out_function : void http_request::parse(std::string request)");
551 /*------ DEBUG LOG END ------*/
555 * Rebuild HTTP request header function.
557 void http_request::rebuild()
559 /*-------- DEBUG LOG --------*/
560 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
561 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 41,
562 "in_function : void http_request::rebuild()");
564 /*------ DEBUG LOG END ------*/
566 this->raw_message = this->request_line();
567 http_message::rebuild();
569 /*-------- DEBUG LOG --------*/
570 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
571 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 42,
572 "out_function : void http_request::rebuild()");
574 /*------ DEBUG LOG END ------*/