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, 1, // XXX log
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, 1, // XXX log
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, 2, // XXX log
66 "in/out_function : Destructor http_request::~http_request(void)");
68 /*------ DEBUG LOG END ------*/
72 * Get method function.
76 std::string http_request::method()
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, 3, // XXX log
81 "in_function : std::string http_request::method(void)");
82 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
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, 3, // XXX log
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, 3, // XXX log
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()
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, 3, // XXX log
133 "in_function : std::string http_request::request_uri(void)");
134 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
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, 3, // XXX log
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, 3, // XXX log
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()
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, 3, // XXX log
185 "in_function : std::string http_request::http_version(void)");
186 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
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, 3, // XXX log
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, 3, // XXX log
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()
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, 3, // XXX log
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, 3, // XXX log
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, 3, // XXX log
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, 3, // XXX log
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, 3, // XXX log
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;
329 * METHOD SP REQUEST-URI SP HTTP-VERSION CRLF
335 if (*ptr == ' ') { // METHOD end with SP
336 this->_method.assign(start, ptr);
337 pos = REQUEST_METHOD_SP;
338 } else if (!isalpha(*ptr) && !isdigit(*ptr)) { // XXX not enough
339 /*-------- DEBUG LOG --------*/
340 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
341 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
342 "out_function : void http_request::parse(std::string request) : Invalid Method");
344 /*------ DEBUG LOG END ------*/
349 * REQUEST-URI : * | absolute-URI | path-absolute | authority
352 * absolute-URI : scheme ":" hier-part [ "?" query ]
353 * path-absolute : "/" [ segment-nz *( "/" segment ) ]
354 * authority : [ userinfo "@" ] host [ ":" port ]
355 * scheme : ALPHA *( ALPHA | DIGIT | "+" | "-" | "." )
356 * hier-part : "//" authority path-abempty
360 * query : *( pchar | "/" | "?" )
361 * path-abempty : *( "/" segment )
362 * path-rootless : segment-nz *( "/" segment )
363 * path-empty : no char
364 * segment-nz : 1*pchar
366 * userinfo : *( unreserved | pct-encoded | sub-delims | ":" )
367 * host : IP-literal | IPv4address | reg-name
369 * unreserved : ALPHA | DIGIT | "-" | "." | "_" | "~"
370 * pct-encoded : "%" HEXDIG HEXDIG
371 * sub-delims : !$&'()*+,;=
372 * pchar : unreserved | pct-encoded | subdelims | ":" | "@"
373 * IP-literal : "[" ( IPv6address | IPvFuture ) "]"
374 * IPvFuture : "v" 1*HEXDIG "." 1*( unreserved | sub-delims | ":" )
375 * IPv6address : 6( h16 ":" ) ls32
376 * / "::" 5( h16 ":" ) ls32
377 * / [ h16 ] "::" 4( h16 ":" ) ls32
378 * / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
379 * / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
380 * / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
381 * / [ *4( h16 ":" ) h16 ] "::" ls32
382 * / [ *5( h16 ":" ) h16 ] "::" h16
383 * / [ *6( h16 ":" ) h16 ] "::"
385 * ls32 : ( h16 ":" h16 ) | IPv4address
386 * IPv4address : dec-octet "." dec-octet "." dec-octet "." dec-octet
388 * reg-name : *( unreserved | pct-encoded | sub-delims )
390 case REQUEST_METHOD_SP:
393 if (*ptr == '/' || isalpha(*ptr) || isdigit(*ptr) || *ptr == '-' ||
394 *ptr == '.' || *ptr == '_' || *ptr == '~' || *ptr == ':' ||
395 *ptr == '@' || *ptr == '!' || *ptr == '$' || *ptr == '&' ||
396 *ptr == '(' || *ptr == ')' || *ptr == '*' || *ptr == '+' ||
397 *ptr == ',' || *ptr == ';' || *ptr == '=' || *ptr == '%') {
398 pos = REQUEST_REQUEST_URI;
401 /*-------- DEBUG LOG --------*/
402 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
403 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
404 "out_function : void http_request::parse(std::string request) : Invalid Request-URI");
406 /*------ DEBUG LOG END ------*/
411 case REQUEST_REQUEST_URI:
412 if (*ptr == ' ') { // Request-URI end with SP
413 this->_request_uri.assign(start, ptr);
414 pos = REQUEST_REQUEST_URI_SP;
415 } else if (!isalpha(*ptr) && !isdigit(*ptr) && *ptr != '/' && // XXX not enough?
416 *ptr != '.' && *ptr != '=' && *ptr != '%' && *ptr != '?' &&
417 *ptr != '&' && *ptr != '+' && *ptr != '~' && *ptr != ',' &&
418 *ptr != '@' && *ptr != '!' && *ptr != '$' && *ptr != '-' &&
419 *ptr != '(' && *ptr != ')' && *ptr != '*' && *ptr != '_' &&
420 *ptr != ':' && *ptr != ';') {
421 /*-------- DEBUG LOG --------*/
422 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
423 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
424 "out_function : void http_request::parse(std::string request) : Invalid Request-URI");
426 /*------ DEBUG LOG END ------*/
432 * HTTP-VERSION : "HTTP" "/" 1*DIGIT "." 1*DIGIT
434 case REQUEST_REQUEST_URI_SP:
435 // HTTP-VERSION start
437 pos = REQUEST_HTTP_VERSION_H;
440 /*-------- DEBUG LOG --------*/
441 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
442 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
443 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
445 /*------ DEBUG LOG END ------*/
450 case REQUEST_HTTP_VERSION_H:
453 pos = REQUEST_HTTP_VERSION_T1;
455 /*-------- DEBUG LOG --------*/
456 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
457 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
458 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
460 /*------ DEBUG LOG END ------*/
465 case REQUEST_HTTP_VERSION_T1:
468 pos = REQUEST_HTTP_VERSION_T2;
470 /*-------- DEBUG LOG --------*/
471 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
472 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
473 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
475 /*------ DEBUG LOG END ------*/
480 case REQUEST_HTTP_VERSION_T2:
483 pos = REQUEST_HTTP_VERSION_P;
485 /*-------- DEBUG LOG --------*/
486 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
487 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
488 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
490 /*------ DEBUG LOG END ------*/
495 case REQUEST_HTTP_VERSION_P:
498 pos = REQUEST_HTTP_VERSION_SLASH;
500 /*-------- DEBUG LOG --------*/
501 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
502 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
503 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
505 /*------ DEBUG LOG END ------*/
510 case REQUEST_HTTP_VERSION_SLASH:
511 // HTTP-VERSION Mejor number
513 pos = REQUEST_HTTP_VERSION_MAJOR;
515 /*-------- DEBUG LOG --------*/
516 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
517 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
518 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
520 /*------ DEBUG LOG END ------*/
525 case REQUEST_HTTP_VERSION_MAJOR:
526 // HTTP-VERSION next dot
528 pos = REQUEST_HTTP_VERSION_DOT;
529 } else if (!isdigit(*ptr)) {
530 /*-------- DEBUG LOG --------*/
531 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
532 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
533 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
535 /*------ DEBUG LOG END ------*/
540 case REQUEST_HTTP_VERSION_DOT:
541 // HTTP-VERSION Minor number
543 pos = REQUEST_HTTP_VERSION_MINOR;
545 /*-------- DEBUG LOG --------*/
546 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
547 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
548 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
550 /*------ DEBUG LOG END ------*/
555 case REQUEST_HTTP_VERSION_MINOR:
556 // HTTP-VERSION end with CR
559 this->_http_version.assign(start, ptr);
560 } else if (!isdigit(*ptr)) {
561 /*-------- DEBUG LOG --------*/
562 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
563 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
564 "out_function : void http_request::parse(std::string request) : Invalid HTTP-Version");
566 /*------ DEBUG LOG END ------*/
575 http_message::parse(std::string(ptr + 1, end));
577 /*-------- DEBUG LOG --------*/
578 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
579 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
580 "out_function : void http_request::parse(std::string request) : not CRLF");
582 /*------ DEBUG LOG END ------*/
587 if (pos == REQUEST_LF)
592 /*-------- DEBUG LOG --------*/
593 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
594 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
595 "out_function : void http_request::parse(std::string request)");
597 /*------ DEBUG LOG END ------*/
601 * Rebuild HTTP request header function.
603 void http_request::rebuild()
605 /*-------- DEBUG LOG --------*/
606 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
607 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
608 "in_function : void http_request::rebuild()");
610 /*------ DEBUG LOG END ------*/
612 this->raw_message = this->request_line();
613 http_message::rebuild();
615 /*-------- DEBUG LOG --------*/
616 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT_HTTP)) {
617 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT_HTTP, 3, // XXX log
618 "out_function : void http_request::rebuild()");
620 /*------ DEBUG LOG END ------*/