Monero
Loading...
Searching...
No Matches
http_protocol_handler.inl
Go to the documentation of this file.
1// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution.
11// * Neither the name of the Andrey N. Sabelnikov nor the
12// names of its contributors may be used to endorse or promote products
13// derived from this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26
27
28#include <boost/algorithm/string/predicate.hpp>
29#include <boost/lexical_cast.hpp>
30#include <boost/regex.hpp>
32#include "reg_exp_definer.h"
33#include "string_tools.h"
34#include "file_io_utils.h"
35#include "net_parse_helpers.h"
36#include "time_helper.h"
37
38#undef MONERO_DEFAULT_LOG_CATEGORY
39#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
40
41#define HTTP_MAX_URI_LEN 9000
42#define HTTP_MAX_HEADER_LEN 100000
43#define HTTP_MAX_STARTING_NEWLINES 8
44
45namespace epee
46{
47namespace net_utils
48{
49 namespace http
50 {
51
53 {
54 std::list<std::pair<std::string, std::string> > m_etc_header_fields;
56 std::string m_content_type;
57 std::string m_body;
58 };
59
60 inline
61 bool match_boundary(const std::string& content_type, std::string& boundary)
62 {
63 STATIC_REGEXP_EXPR_1(rexp_match_boundary, "boundary=(.*?)(($)|([;\\s,]))", boost::regex::icase | boost::regex::normal);
64 // 1
65 boost::smatch result;
66 if(boost::regex_search(content_type, result, rexp_match_boundary, boost::match_default) && result[0].matched)
67 {
68 boundary = result[1];
69 return true;
70 }
71
72 return false;
73 }
74
75 inline
76 bool parse_header(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry& entry)
77 {
78 STATIC_REGEXP_EXPR_1(rexp_mach_field,
79 "\n?((Content-Disposition)|(Content-Type)"
80 // 12 3
81 "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]",
82 //4 56 7
83 boost::regex::icase | boost::regex::normal);
84
85 boost::smatch result;
86 std::string::const_iterator it_current_bound = it_begin;
87 std::string::const_iterator it_end_bound = it_end;
88
89 //lookup all fields and fill well-known fields
90 while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched)
91 {
92 const size_t field_val = 6;
93 const size_t field_etc_name = 4;
94
95 int i = 2; //start position = 2
96 if(result[i++].matched)//"Content-Disposition"
97 entry.m_content_disposition = result[field_val];
98 else if(result[i++].matched)//"Content-Type"
99 entry.m_content_type = result[field_val];
100 else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
101 entry.m_etc_header_fields.push_back(std::pair<std::string, std::string>(result[field_etc_name], result[field_val]));
102 else
103 {
104 LOG_ERROR("simple_http_connection_handler::parse_header() not matched last entry in:"<<std::string(it_current_bound, it_end));
105 }
106
107 it_current_bound = result[(int)result.size()-1].first;
108 }
109 return true;
110 }
111
112 inline
113 bool handle_part_of_multipart(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry& entry)
114 {
115 std::string end_str = "\r\n\r\n";
116 std::string::const_iterator end_header_it = std::search(it_begin, it_end, end_str.begin(), end_str.end());
117 if(end_header_it == it_end)
118 {
119 //header not matched
120 return false;
123 if(!parse_header(it_begin, end_header_it+4, entry))
125 LOG_ERROR("Failed to parse header:" << std::string(it_begin, end_header_it+2));
126 return false;
129 entry.m_body.assign(end_header_it+4, it_end);
131 return true;
132 }
134 inline
135 bool parse_multipart_body(const std::string& content_type, const std::string& body, std::list<multipart_entry>& out_values)
137 //bool res = file_io_utils::load_file_to_string("C:\\public\\multupart_data", body);
138
139 std::string boundary;
140 if(!match_boundary(content_type, boundary))
141 {
142 MERROR("Failed to match boundary in content type: " << content_type);
143 return false;
144 }
145
146 boundary+="\r\n";
147 bool is_stop = false;
148 bool first_step = true;
149
150 std::string::const_iterator it_begin = body.begin();
151 std::string::const_iterator it_end;
152 while(!is_stop)
153 {
154 std::string::size_type pos = body.find(boundary, std::distance(body.begin(), it_begin));
155
156 if(std::string::npos == pos)
157 {
158 is_stop = true;
159 boundary.erase(boundary.size()-2, 2);
160 boundary+= "--";
161 pos = body.find(boundary, std::distance(body.begin(), it_begin));
162 if(std::string::npos == pos)
163 {
164 MERROR("Error: Filed to match closing multipart tag");
165 it_end = body.end();
166 }else
167 {
168 it_end = body.begin() + pos;
169 }
170 }else
171 it_end = body.begin() + pos;
172
173
174 if(first_step && !is_stop)
175 {
176 first_step = false;
177 it_begin = it_end + boundary.size();
178 std::string temp = "\r\n--";
179 boundary = temp + boundary;
180 continue;
181 }
182
183 out_values.push_back(multipart_entry());
184 if(!handle_part_of_multipart(it_begin, it_end, out_values.back()))
185 {
186 MERROR("Failed to handle_part_of_multipart");
187 return false;
188 }
189
190 it_begin = it_end + boundary.size();
191 }
192
193 return true;
194 }
195
196
197
198
199 //--------------------------------------------------------------------------------------------
200 template<class t_connection_context>
217 //--------------------------------------------------------------------------------------------
218 template<class t_connection_context>
220 {
221 try
222 {
223 if (m_initialized)
224 {
226 if (m_config.m_connection_count)
227 --m_config.m_connection_count;
228 auto elem = m_config.m_connections.find(m_conn_context.m_remote_address.host_str());
229 if (elem != m_config.m_connections.end())
230 {
231 if (elem->second == 1 || elem->second == 0)
232 m_config.m_connections.erase(elem);
233 else
234 --(elem->second);
235 }
236 }
237 }
238 catch (...)
239 {}
240 }
241 //--------------------------------------------------------------------------------------------
242 template<class t_connection_context>
244 {
246 ++m_config.m_connections[m_conn_context.m_remote_address.host_str()];
247 ++m_config.m_connection_count;
248 m_initialized = true;
249 return true;
250 }
251 //--------------------------------------------------------------------------------------------
252 template<class t_connection_context>
264 //--------------------------------------------------------------------------------------------
265 template<class t_connection_context>
267 {
268 std::string buf((const char*)ptr, cb);
269 //LOG_PRINT_L0("HTTP_RECV: " << ptr << "\r\n" << buf);
270 //file_io_utils::save_string_to_file(string_tools::get_current_module_folder() + "/" + boost::lexical_cast<std::string>(ptr), std::string((const char*)ptr, cb));
271
272 bool res = handle_buff_in(buf);
273 if(m_want_close/*m_state == http_state_connection_close || m_state == http_state_error*/)
274 return false;
275 return res;
276 }
277 //--------------------------------------------------------------------------------------------
278 template<class t_connection_context>
280 {
281
282 size_t ndel;
283
284 m_bytes_read += buf.size();
285 if (m_bytes_read > m_config.m_max_content_length)
286 {
287 LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too much data: got " << m_bytes_read);
289 return false;
290 }
291
292 if(m_cache.size())
293 m_cache += buf;
294 else
295 m_cache.swap(buf);
296
297 m_is_stop_handling = false;
298 while(!m_is_stop_handling)
299 {
300 switch(m_state)
301 {
303 //The HTTP protocol does not place any a priori limit on the length of a URI. (c)RFC2616
304 //but we forebly restirct it len to HTTP_MAX_URI_LEN to make it more safely
305 if(!m_cache.size())
306 break;
307
308 //check_and_handle_fake_response();
309 ndel = m_cache.find_first_not_of("\r\n");
310 if (ndel != 0)
311 {
312 //some times it could be that before query line cold be few line breaks
313 //so we have to be calm without panic with assers
314 m_newlines += std::string::npos == ndel ? m_cache.size() : ndel;
316 {
317 LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too many starting newlines");
319 return false;
320 }
321 m_cache.erase(0, ndel);
322 break;
323 }
324
325 if(std::string::npos != m_cache.find('\n', 0))
327 else
328 {
329 m_is_stop_handling = true;
330 if(m_cache.size() > HTTP_MAX_URI_LEN)
331 {
332 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_buff_out: Too long URI line");
334 return false;
335 }
336 }
337 break;
339 {
340 std::string::size_type pos = match_end_of_header(m_cache);
341 if(std::string::npos == pos)
342 {
343 m_is_stop_handling = true;
344 if(m_cache.size() > HTTP_MAX_HEADER_LEN)
345 {
346 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_buff_in: Too long header area");
348 return false;
349 }
350 break;
351 }
353 return false;
354 break;
355 }
359 return false;
360 default:
361 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_char_out: Wrong state: " << m_state);
362 return false;
363 case http_state_error:
364 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler::handle_char_out: Error state!!!");
365 return false;
366 }
367
368 if(!m_cache.size())
369 m_is_stop_handling = true;
370 }
371
372 return true;
373 }
374 //--------------------------------------------------------------------------------------------
375 inline bool analize_http_method(const boost::smatch& result, http::http_method& method, int& http_ver_major, int& http_ver_minor)
376 {
377 CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed...");
378 if (!boost::conversion::try_lexical_convert<int>(result[11], http_ver_major))
379 return false;
380 if (!boost::conversion::try_lexical_convert<int>(result[12], http_ver_minor))
381 return false;
382
383 if(result[3].matched)
385 else if(result[4].matched)
386 method = http::http_method_get;
387 else if(result[5].matched)
388 method = http::http_method_head;
389 else if(result[6].matched)
390 method = http::http_method_post;
391 else if(result[7].matched)
392 method = http::http_method_put;
393 else
394 method = http::http_method_etc;
395
396 return true;
397 }
398
399 //--------------------------------------------------------------------------------------------
400 template<class t_connection_context>
402 {
403 STATIC_REGEXP_EXPR_1(rexp_match_command_line, "^(((OPTIONS)|(GET)|(HEAD)|(POST)|(PUT)|(DELETE)|(TRACE)) (\\S+) HTTP/(\\d+)\\.(\\d+))\r?\n", boost::regex::icase | boost::regex::normal);
404 // 123 4 5 6 7 8 9 10 11 12
405 //size_t match_len = 0;
406 boost::smatch result;
407 if(boost::regex_search(m_cache, result, rexp_match_command_line, boost::match_default) && result[0].matched)
408 {
409 if (!analize_http_method(result, m_query_info.m_http_method, m_query_info.m_http_ver_hi, m_query_info.m_http_ver_hi))
410 {
412 MERROR("Failed to analyze method");
413 return false;
414 }
415 m_query_info.m_URI = result[10];
416 if (!parse_uri(m_query_info.m_URI, m_query_info.m_uri_content))
417 {
419 MERROR("Failed to parse URI: m_query_info.m_URI");
420 return false;
421 }
422 m_query_info.m_http_method_str = result[2];
423 m_query_info.m_full_request_str = result[0];
424
425 m_cache.erase(m_cache.begin(), result[0].second);
426
428
429 return true;
430 }else
431 {
433 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::handle_invoke_query_line(): Failed to match first line: " << m_cache);
434 return false;
435 }
436
437 return false;
438 }
439 //--------------------------------------------------------------------------------------------
440 template<class t_connection_context>
442 {
443
444 //Here we returning head size, including terminating sequence (\r\n\r\n or \n\n)
445 std::string::size_type res = buf.find("\r\n\r\n");
446 if(std::string::npos != res)
447 return res+4;
448 res = buf.find("\n\n");
449 if(std::string::npos != res)
450 return res+2;
451 return res;
452 }
453 //--------------------------------------------------------------------------------------------
454 template<class t_connection_context>
456 {
457 LOG_PRINT_L3("HTTP HEAD:\r\n" << m_cache.substr(0, pos));
458
459 m_query_info.m_full_request_buf_size = pos;
460 m_query_info.m_request_head.assign(m_cache.begin(), m_cache.begin()+pos);
461
462 if(!parse_cached_header(m_query_info.m_header_info, m_cache, pos))
463 {
464 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache);
466 return false;
467 }
468
469 m_cache.erase(0, pos);
470
471 std::string req_command_str = m_query_info.m_full_request_str;
472 //if we have POST or PUT command, it is very possible tha we will get body
473 //but now, we suppose than we have body only in case of we have "ContentLength"
474 if(m_query_info.m_header_info.m_content_length.size())
475 {
478 if(!get_len_from_content_lenght(m_query_info.m_header_info.m_content_length, m_len_summary))
479 {
480 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length="<<m_query_info.m_header_info.m_content_length);
482 return false;
483 }
484 if(0 == m_len_summary)
485 { //current query finished, next will be next query
488 else
490 }
492 }else
493 {//current query finished, next will be next query
496 }
497
498 return true;
499 }
500 //-----------------------------------------------------------------------------------
501 template<class t_connection_context>
503 {
505 {
507 return handle_query_measure();
512 default:
513 LOG_ERROR_CC(m_conn_context, "simple_http_connection_handler<t_connection_context>::handle_retriving_query_body(): Unexpected m_body_query_type state:" << m_body_transfer_type);
515 return false;
516 }
517
518 return true;
519 }
520 //-----------------------------------------------------------------------------------
521 template<class t_connection_context>
523 {
524
525 if(m_len_remain >= m_cache.size())
526 {
527 m_len_remain -= m_cache.size();
528 m_query_info.m_body += m_cache;
529 m_cache.clear();
530 }else
531 {
532 m_query_info.m_body.append(m_cache.begin(), m_cache.begin() + m_len_remain);
533 m_cache.erase(0, m_len_remain);
534 m_len_remain = 0;
535 }
536
537 if(!m_len_remain)
538 {
541 else
543 }
544 return true;
545 }
546 //--------------------------------------------------------------------------------------------
547 template<class t_connection_context>
548 bool simple_http_connection_handler<t_connection_context>::parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos)
549 {
550 body_info.clear();
551 if(pos > m_cache_to_process.size() || pos > HTTP_MAX_HEADER_LEN)
552 return false;
553
554 size_t cur = 0;
555
556 while(cur < pos)
557 {
558 const size_t line_end = m_cache_to_process.find('\n', cur);
559 if(line_end == std::string::npos || line_end >= pos)
560 break;
561
562 boost::string_view line(m_cache_to_process.data() + cur, line_end - cur);
563 cur = line_end + 1;
564
565 // End of header block.
566 if(line == "\r" || line.empty())
567 break;
568
569 boost::string_view name;
570 boost::string_view value;
571 if(!detail::parse_header_line(line, name, value))
572 return false;
573
574 if(boost::iequals(name, "Connection"))
575 body_info.m_connection = std::string(value.data(), value.size());
576 else if(boost::iequals(name, "Referer"))
577 body_info.m_referer = std::string(value.data(), value.size());
578 else if(boost::iequals(name, "Content-Length"))
579 body_info.m_content_length = std::string(value.data(), value.size());
580 else if(boost::iequals(name, "Content-Type"))
581 body_info.m_content_type = std::string(value.data(), value.size());
582 else if(boost::iequals(name, "Transfer-Encoding"))
583 body_info.m_transfer_encoding = std::string(value.data(), value.size());
584 else if(boost::iequals(name, "Content-Encoding"))
585 body_info.m_content_encoding = std::string(value.data(), value.size());
586 else if(boost::iequals(name, "Host"))
587 body_info.m_host = std::string(value.data(), value.size());
588 else if(boost::iequals(name, "Cookie"))
589 body_info.m_cookie = std::string(value.data(), value.size());
590 else if(boost::iequals(name, "User-Agent"))
591 body_info.m_user_agent = std::string(value.data(), value.size());
592 else if(boost::iequals(name, "Origin"))
593 body_info.m_origin = std::string(value.data(), value.size());
594 else
595 body_info.m_etc_fields.push_back(std::make_pair(std::string(name.data(), name.size()), std::string(value.data(), value.size())));
596 }
597 return true;
598 }
599 //-----------------------------------------------------------------------------------
600 template<class t_connection_context>
602 {
603 STATIC_REGEXP_EXPR_1(rexp_mach_field, "\\d+", boost::regex::normal);
604 std::string res;
605 boost::smatch result;
606 if(!(boost::regex_search( str, result, rexp_mach_field, boost::match_default) && result[0].matched))
607 return false;
608
609 try { len = boost::lexical_cast<size_t>(result[0]); }
610 catch(...) { return false; }
611 return true;
612 }
613 //-----------------------------------------------------------------------------------
614 template<class t_connection_context>
616 {
617 http_response_info response{};
618 //CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" );
619 bool res = true;
620
622 {
623 res = handle_request(query_info, response);
624 if (response.m_response_code == 500)
625 {
626 m_want_close = true; // close on all "Internal server error"s
627 }
628 }
629 else
630 {
631 response.m_response_code = 200;
632 response.m_response_comment = "OK";
633 }
634
635 std::string response_data = get_response_header(response);
636 //LOG_PRINT_L0("HTTP_SEND: << \r\n" << response_data + response.m_body);
637
638 LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" << response_data);
639
640 if ((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options))
641 response_data += response.m_body;
642
643 m_psnd_hndlr->do_send(byte_slice{std::move(response_data)});
644 m_psnd_hndlr->send_done();
645 return res;
646 }
647 //-----------------------------------------------------------------------------------
648 template<class t_connection_context>
650 {
651
652 std::string uri_to_path = query_info.m_uri_content.m_path;
653 if("/" == uri_to_path)
654 uri_to_path = "/index.html";
655
656 //slash_to_back_slash(uri_to_path);
657 m_config.m_lock.lock();
658 std::string destination_file_path = m_config.m_folder + uri_to_path;
659 m_config.m_lock.unlock();
660 if(!file_io_utils::load_file_to_string(destination_file_path.c_str(), response.m_body))
661 {
662 MWARNING("URI \""<< query_info.m_full_request_str.substr(0, query_info.m_full_request_str.size()-2) << "\" [" << destination_file_path << "] Not Found (404 )");
663 response.m_body = get_not_found_response_body(query_info.m_URI);
664 response.m_response_code = 404;
665 response.m_response_comment = "Not found";
666 response.m_mime_tipe = "text/html";
667 return true;
668 }
669
670 MDEBUG(" -->> " << query_info.m_full_request_str << "\r\n<<--OK");
671 response.m_response_code = 200;
672 response.m_response_comment = "OK";
673 response.m_mime_tipe = get_file_mime_tipe(uri_to_path);
674
675 return true;
676 }
677 //-----------------------------------------------------------------------------------
678 template<class t_connection_context>
680 {
681 std::string buf = "HTTP/1.1 ";
682 buf += boost::lexical_cast<std::string>(response.m_response_code) + " " + response.m_response_comment + "\r\n" +
683 "Server: Epee-based\r\n"
684 "Content-Length: ";
685 buf += boost::lexical_cast<std::string>(response.m_body.size()) + "\r\n";
686
687 if(!response.m_mime_tipe.empty())
688 {
689 buf += "Content-Type: ";
690 buf += response.m_mime_tipe + "\r\n";
691 }
692
693 buf += "Last-Modified: ";
694 time_t tm;
695 time(&tm);
697 buf += "Accept-Ranges: bytes\r\n";
698 //Wed, 01 Dec 2010 03:27:41 GMT"
699
700 string_tools::trim(m_query_info.m_header_info.m_connection);
701 if(m_query_info.m_header_info.m_connection.size())
702 {
703 if(!string_tools::compare_no_case("close", m_query_info.m_header_info.m_connection))
704 {
705 //closing connection after sending
706 buf += "Connection: close\r\n";
708 m_want_close = true;
709 }
710 }
711
712 // Cross-origin resource sharing
713 if(m_query_info.m_header_info.m_origin.size())
714 {
715 if (std::binary_search(m_config.m_access_control_origins.begin(), m_config.m_access_control_origins.end(), "*") || std::binary_search(m_config.m_access_control_origins.begin(), m_config.m_access_control_origins.end(), m_query_info.m_header_info.m_origin))
716 {
717 buf += "Access-Control-Allow-Origin: ";
718 buf += m_query_info.m_header_info.m_origin;
719 buf += "\r\n";
720 buf += "Access-Control-Expose-Headers: www-authenticate\r\n";
721 if (m_query_info.m_http_method == http::http_method_options)
722 buf += "Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With\r\n";
723 buf += "Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS\r\n";
724 }
725 }
726
727 //add additional fields, if it is
728 for(fields_list::const_iterator it = response.m_additional_fields.begin(); it!=response.m_additional_fields.end(); it++)
729 buf += it->first + ": " + it->second + "\r\n";
730
731 buf+="\r\n";
732
733 return buf;
734 }
735 //-----------------------------------------------------------------------------------
736 template<class t_connection_context>
738 {
739 std::string result;
740 std::string ext = string_tools::get_extension(path);
741 if(!string_tools::compare_no_case(ext, "gif"))
742 result = "image/gif";
743 else if(!string_tools::compare_no_case(ext, "jpg"))
744 result = "image/jpeg";
745 else if(!string_tools::compare_no_case(ext, "html"))
746 result = "text/html";
747 else if(!string_tools::compare_no_case(ext, "htm"))
748 result = "text/html";
749 else if(!string_tools::compare_no_case(ext, "js"))
750 result = "application/x-javascript";
751 else if(!string_tools::compare_no_case(ext, "css"))
752 result = "text/css";
753 else if(!string_tools::compare_no_case(ext, "xml"))
754 result = "application/xml";
755 else if(!string_tools::compare_no_case(ext, "svg"))
756 result = "image/svg+xml";
757
758
759 return result;
760 }
761 //-----------------------------------------------------------------------------------
762 template<class t_connection_context>
764 {
765 std::string body =
766 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
767 "<html><head>\r\n"
768 "<title>404 Not Found</title>\r\n"
769 "</head><body>\r\n"
770 "<h1>Not Found</h1>\r\n"
771 "<p>The requested URL \r\n";
772 body += URI;
773 body += "was not found on this server.</p>\r\n"
774 "</body></html>\r\n";
775
776 return body;
777 }
778 //--------------------------------------------------------------------------------------------
779 template<class t_connection_context>
781 {
782 for(std::string::iterator it = str.begin(); it!=str.end(); it++)
783 if('/' == *it)
784 *it = '\\';
785 return true;
786 }
787 }
788}
789}
790
791//--------------------------------------------------------------------------------------------
792//--------------------------------------------------------------------------------------------
793//--------------------------------------------------------------------------------------------
Definition byte_slice.h:69
size_t m_bytes_read
Definition http_protocol_handler.h:148
config_type & m_config
Definition http_protocol_handler.h:145
bool get_len_from_content_lenght(const std::string &str, size_t &len)
Definition http_protocol_handler.inl:601
bool parse_cached_header(http_header_info &body_info, const std::string &m_cache_to_process, size_t pos)
Definition http_protocol_handler.inl:548
@ http_body_transfer_measure
Definition http_protocol_handler.h:110
@ http_body_transfer_undefined
Definition http_protocol_handler.h:114
@ http_body_transfer_connection_close
Definition http_protocol_handler.h:112
@ http_body_transfer_multipart
Definition http_protocol_handler.h:113
@ http_body_transfer_chunked
Definition http_protocol_handler.h:109
i_service_endpoint * m_psnd_hndlr
Definition http_protocol_handler.h:150
bool after_init_connection()
Definition http_protocol_handler.inl:243
virtual ~simple_http_connection_handler()
Definition http_protocol_handler.inl:219
std::string m_cache
Definition http_protocol_handler.h:139
bool handle_retriving_query_body()
Definition http_protocol_handler.inl:502
bool slash_to_back_slash(std::string &str)
Definition http_protocol_handler.inl:780
@ http_state_retriving_body
Definition http_protocol_handler.h:103
@ http_state_connection_close
Definition http_protocol_handler.h:104
@ http_state_error
Definition http_protocol_handler.h:105
@ http_state_retriving_header
Definition http_protocol_handler.h:102
@ http_state_retriving_comand_line
Definition http_protocol_handler.h:101
size_t m_newlines
Definition http_protocol_handler.h:147
http::http_request_info m_query_info
Definition http_protocol_handler.h:143
machine_state m_state
Definition http_protocol_handler.h:140
bool m_initialized
Definition http_protocol_handler.h:152
std::string get_file_mime_tipe(const std::string &path)
Definition http_protocol_handler.inl:737
bool handle_invoke_query_line()
Definition http_protocol_handler.inl:401
bool handle_buff_in(std::string &buf)
Definition http_protocol_handler.inl:279
bool handle_query_measure()
Definition http_protocol_handler.inl:522
body_transfer_type m_body_transfer_type
Definition http_protocol_handler.h:141
bool set_ready_state()
Definition http_protocol_handler.inl:253
bool handle_request_and_send_response(const http::http_request_info &query_info)
Definition http_protocol_handler.inl:615
size_t m_len_remain
Definition http_protocol_handler.h:144
t_connection_context & m_conn_context
Definition http_protocol_handler.h:151
bool analize_cached_request_header_and_invoke_state(size_t pos)
Definition http_protocol_handler.inl:455
std::string get_response_header(const http_response_info &response)
Definition http_protocol_handler.inl:679
std::string::size_type match_end_of_header(const std::string &buf)
Definition http_protocol_handler.inl:441
virtual bool handle_request(const http::http_request_info &query_info, http_response_info &response)
Definition http_protocol_handler.inl:649
bool m_is_stop_handling
Definition http_protocol_handler.h:142
virtual bool handle_recv(const void *ptr, size_t cb)
Definition http_protocol_handler.inl:266
http_server_config config_type
Definition http_protocol_handler.h:76
bool m_want_close
Definition http_protocol_handler.h:146
std::string get_not_found_response_body(const std::string &URI)
Definition http_protocol_handler.inl:763
simple_http_connection_handler(i_service_endpoint *psnd_hndlr, config_type &config, t_connection_context &conn_context)
Definition http_protocol_handler.inl:201
size_t m_len_summary
Definition http_protocol_handler.h:144
#define false
const char * res
Definition hmac_keccak.cpp:42
#define HTTP_MAX_STARTING_NEWLINES
Definition http_protocol_handler.inl:43
#define HTTP_MAX_URI_LEN
Definition http_protocol_handler.inl:41
#define HTTP_MAX_HEADER_LEN
Definition http_protocol_handler.inl:42
Definition cryptonote_config.h:221
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
Definition file_io_utils.cpp:105
std::string get_internet_time_str(const time_t &time_)
Definition time_helper.h:49
bool parse_header_line(boost::string_view line, boost::string_view &name, boost::string_view &value)
Definition http_base.h:85
http_method
Definition http_base.h:49
@ http_method_head
Definition http_base.h:54
@ http_method_etc
Definition http_base.h:55
@ http_method_put
Definition http_base.h:53
@ http_method_get
Definition http_base.h:51
@ http_method_post
Definition http_base.h:52
@ http_method_options
Definition http_base.h:50
bool match_boundary(const std::string &content_type, std::string &boundary)
Definition http_protocol_handler.inl:61
bool parse_header(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry &entry)
Definition http_protocol_handler.inl:76
bool parse_multipart_body(const std::string &content_type, const std::string &body, std::list< multipart_entry > &out_values)
Definition http_protocol_handler.inl:135
bool analize_http_method(const boost::smatch &result, http::http_method &method, int &http_ver_major, int &http_ver_minor)
Definition http_protocol_handler.inl:375
bool handle_part_of_multipart(std::string::const_iterator it_begin, std::string::const_iterator it_end, multipart_entry &entry)
Definition http_protocol_handler.inl:113
bool parse_uri(const std::string uri, http::uri_content &content)
Definition net_parse_helpers.cpp:102
std::string get_extension(const std::string &str)
Definition string_tools.cpp:193
bool compare_no_case(const std::string &str1, const std::string &str2)
Definition string_tools.cpp:136
std::string & trim(std::string &str)
Definition string_tools.h:75
TODO: (mj-xmr) This will be reduced in an another PR.
Definition byte_slice.h:40
#define LOG_ERROR_CC(ct, message)
Definition net_utils_base.h:469
const GenericPointer< typename T::ValueType > T2 value
Definition pointer.h:1225
#define STATIC_REGEXP_EXPR_1(var_name, xpr_text, reg_exp_flags)
Definition reg_exp_definer.h:48
tools::wallet2::message_signature_result_t result
Definition signature.cpp:62
const char * buf
Definition slow_memmem.cpp:73
#define OUT
Definition string_tools.h:40
Definition http_base.h:121
fields_list m_etc_fields
Definition http_base.h:132
std::string m_content_length
Definition http_base.h:124
std::string m_content_encoding
Definition http_base.h:127
std::string m_origin
Definition http_base.h:131
std::string m_referer
Definition http_base.h:123
std::string m_cookie
Definition http_base.h:129
void clear()
Definition http_base.h:134
std::string m_connection
Definition http_base.h:122
std::string m_user_agent
Definition http_base.h:130
std::string m_content_type
Definition http_base.h:125
std::string m_transfer_encoding
Definition http_base.h:126
std::string m_host
Definition http_base.h:128
std::string m_full_request_str
Definition http_base.h:180
uri_content m_uri_content
Definition http_base.h:187
http_method m_http_method
Definition http_base.h:177
std::string m_URI
Definition http_base.h:178
std::string m_response_comment
Definition http_base.h:202
std::string m_mime_tipe
Definition http_base.h:205
int m_response_code
Definition http_base.h:201
std::string m_body
Definition http_base.h:204
fields_list m_additional_fields
Definition http_base.h:203
Definition http_protocol_handler.inl:53
std::string m_body
Definition http_protocol_handler.inl:57
std::list< std::pair< std::string, std::string > > m_etc_header_fields
Definition http_protocol_handler.inl:54
std::string m_content_type
Definition http_protocol_handler.inl:56
std::string m_content_disposition
Definition http_protocol_handler.inl:55
std::string m_path
Definition http_base.h:152
Definition net_utils_base.h:442
#define CRITICAL_REGION_LOCAL(x)
Definition syncobj.h:153