diff --git a/master/reference/http__connection_8h_source.html b/master/reference/http__connection_8h_source.html
index 743a6ff1e..2fa8ad390 100644
--- a/master/reference/http__connection_8h_source.html
+++ b/master/reference/http__connection_8h_source.html
@@ -359,381 +359,369 @@
-
- 262 std::string location = res.get_header_value(
"Location");
- 263 if (!location.empty() && location.find(
"://", 0) == std::string::npos)
-
- 265 #ifdef CROW_ENABLE_SSL
- 266 if (handler_->ssl_used())
- 267 location.insert(0,
"https://" + req_.get_header_value(
"Host"));
-
-
- 270 location.insert(0,
"http://" + req_.get_header_value(
"Host"));
- 271 res.set_header(
"location", location);
-
+
+
+
+ 264 if (res.is_static_type())
+
+
+
+
+
+
+
+
-
-
- 276 if (res.is_static_type())
-
-
-
-
+
+ 275 void prepare_buffers()
+
+ 277 res.complete_request_handler_ =
nullptr;
+ 278 res.is_alive_helper_ =
nullptr;
+
+ 280 if (!adaptor_.is_open())
-
-
-
-
-
- 287 void prepare_buffers()
-
- 289 res.complete_request_handler_ =
nullptr;
- 290 res.is_alive_helper_ =
nullptr;
+
+
+
+
+
+
+ 288 static std::unordered_map<int, std::string> statusCodes = {
+ 289 {status::CONTINUE,
"HTTP/1.1 100 Continue\r\n"},
+ 290 {status::SWITCHING_PROTOCOLS,
"HTTP/1.1 101 Switching Protocols\r\n"},
- 292 if (!adaptor_.is_open())
-
-
-
-
-
-
-
- 300 static std::unordered_map<int, std::string> statusCodes = {
- 301 {status::CONTINUE,
"HTTP/1.1 100 Continue\r\n"},
- 302 {status::SWITCHING_PROTOCOLS,
"HTTP/1.1 101 Switching Protocols\r\n"},
-
- 304 {status::OK,
"HTTP/1.1 200 OK\r\n"},
- 305 {status::CREATED,
"HTTP/1.1 201 Created\r\n"},
- 306 {status::ACCEPTED,
"HTTP/1.1 202 Accepted\r\n"},
- 307 {status::NON_AUTHORITATIVE_INFORMATION,
"HTTP/1.1 203 Non-Authoritative Information\r\n"},
- 308 {status::NO_CONTENT,
"HTTP/1.1 204 No Content\r\n"},
- 309 {status::RESET_CONTENT,
"HTTP/1.1 205 Reset Content\r\n"},
- 310 {status::PARTIAL_CONTENT,
"HTTP/1.1 206 Partial Content\r\n"},
-
- 312 {status::MULTIPLE_CHOICES,
"HTTP/1.1 300 Multiple Choices\r\n"},
- 313 {status::MOVED_PERMANENTLY,
"HTTP/1.1 301 Moved Permanently\r\n"},
- 314 {status::FOUND,
"HTTP/1.1 302 Found\r\n"},
- 315 {status::SEE_OTHER,
"HTTP/1.1 303 See Other\r\n"},
- 316 {status::NOT_MODIFIED,
"HTTP/1.1 304 Not Modified\r\n"},
- 317 {status::TEMPORARY_REDIRECT,
"HTTP/1.1 307 Temporary Redirect\r\n"},
- 318 {status::PERMANENT_REDIRECT,
"HTTP/1.1 308 Permanent Redirect\r\n"},
-
- 320 {status::BAD_REQUEST,
"HTTP/1.1 400 Bad Request\r\n"},
- 321 {status::UNAUTHORIZED,
"HTTP/1.1 401 Unauthorized\r\n"},
- 322 {status::FORBIDDEN,
"HTTP/1.1 403 Forbidden\r\n"},
- 323 {status::NOT_FOUND,
"HTTP/1.1 404 Not Found\r\n"},
- 324 {status::METHOD_NOT_ALLOWED,
"HTTP/1.1 405 Method Not Allowed\r\n"},
- 325 {status::NOT_ACCEPTABLE,
"HTTP/1.1 406 Not Acceptable\r\n"},
- 326 {status::PROXY_AUTHENTICATION_REQUIRED,
"HTTP/1.1 407 Proxy Authentication Required\r\n"},
- 327 {status::CONFLICT,
"HTTP/1.1 409 Conflict\r\n"},
- 328 {status::GONE,
"HTTP/1.1 410 Gone\r\n"},
- 329 {status::PAYLOAD_TOO_LARGE,
"HTTP/1.1 413 Payload Too Large\r\n"},
- 330 {status::UNSUPPORTED_MEDIA_TYPE,
"HTTP/1.1 415 Unsupported Media Type\r\n"},
- 331 {status::RANGE_NOT_SATISFIABLE,
"HTTP/1.1 416 Range Not Satisfiable\r\n"},
- 332 {status::EXPECTATION_FAILED,
"HTTP/1.1 417 Expectation Failed\r\n"},
- 333 {status::PRECONDITION_REQUIRED,
"HTTP/1.1 428 Precondition Required\r\n"},
- 334 {status::TOO_MANY_REQUESTS,
"HTTP/1.1 429 Too Many Requests\r\n"},
- 335 {status::UNAVAILABLE_FOR_LEGAL_REASONS,
"HTTP/1.1 451 Unavailable For Legal Reasons\r\n"},
-
- 337 {status::INTERNAL_SERVER_ERROR,
"HTTP/1.1 500 Internal Server Error\r\n"},
- 338 {status::NOT_IMPLEMENTED,
"HTTP/1.1 501 Not Implemented\r\n"},
- 339 {status::BAD_GATEWAY,
"HTTP/1.1 502 Bad Gateway\r\n"},
- 340 {status::SERVICE_UNAVAILABLE,
"HTTP/1.1 503 Service Unavailable\r\n"},
- 341 {status::GATEWAY_TIMEOUT,
"HTTP/1.1 504 Gateway Timeout\r\n"},
- 342 {status::VARIANT_ALSO_NEGOTIATES,
"HTTP/1.1 506 Variant Also Negotiates\r\n"},
-
-
- 345 static const std::string seperator =
": ";
-
-
- 348 buffers_.reserve(4 * (res.headers.size() + 5) + 3);
-
- 350 if (!statusCodes.count(res.code))
-
- 352 CROW_LOG_WARNING <<
this <<
" status code "
- 353 <<
"(" << res.code <<
")"
- 354 <<
" not defined, returning 500 instead";
-
-
-
- 358 auto& status = statusCodes.find(res.code)->second;
- 359 buffers_.emplace_back(status.data(), status.size());
-
- 361 if (res.code >= 400 && res.body.empty())
- 362 res.body = statusCodes[res.code].substr(9);
-
- 364 for (
auto& kv : res.headers)
-
- 366 buffers_.emplace_back(kv.first.data(), kv.first.size());
- 367 buffers_.emplace_back(seperator.data(), seperator.size());
- 368 buffers_.emplace_back(kv.second.data(), kv.second.size());
- 369 buffers_.emplace_back(crlf.data(), crlf.size());
-
-
- 372 if (!res.manual_length_header && !res.headers.count(
"content-length"))
-
- 374 content_length_ = std::to_string(res.body.size());
- 375 static std::string content_length_tag =
"Content-Length: ";
- 376 buffers_.emplace_back(content_length_tag.data(), content_length_tag.size());
- 377 buffers_.emplace_back(content_length_.data(), content_length_.size());
- 378 buffers_.emplace_back(crlf.data(), crlf.size());
-
- 380 if (!res.headers.count(
"server"))
-
- 382 static std::string server_tag =
"Server: ";
- 383 buffers_.emplace_back(server_tag.data(), server_tag.size());
- 384 buffers_.emplace_back(server_name_.data(), server_name_.size());
- 385 buffers_.emplace_back(crlf.data(), crlf.size());
-
- 387 if (!res.headers.count(
"date"))
-
- 389 static std::string date_tag =
"Date: ";
- 390 date_str_ = get_cached_date_str();
- 391 buffers_.emplace_back(date_tag.data(), date_tag.size());
- 392 buffers_.emplace_back(date_str_.data(), date_str_.size());
- 393 buffers_.emplace_back(crlf.data(), crlf.size());
-
-
-
- 397 static std::string keep_alive_tag =
"Connection: Keep-Alive";
- 398 buffers_.emplace_back(keep_alive_tag.data(), keep_alive_tag.size());
- 399 buffers_.emplace_back(crlf.data(), crlf.size());
-
-
- 402 buffers_.emplace_back(crlf.data(), crlf.size());
-
-
- 405 void do_write_static()
-
- 407 asio::write(adaptor_.socket(), buffers_);
-
- 409 if (res.file_info.statResult == 0)
-
- 411 std::ifstream is(res.file_info.path.c_str(), std::ios::in | std::ios::binary);
- 412 std::vector<asio::const_buffer> buffers{1};
-
- 414 is.read(buf,
sizeof(buf));
- 415 while (is.gcount() > 0)
-
- 417 buffers[0] = asio::buffer(buf, is.gcount());
- 418 do_write_sync(buffers);
- 419 is.read(buf,
sizeof(buf));
-
-
- 422 if (close_connection_)
-
- 424 adaptor_.shutdown_readwrite();
-
- 426 CROW_LOG_DEBUG <<
this <<
" from write (static)";
-
-
-
-
-
-
-
-
- 435 void do_write_general()
-
- 437 if (res.body.length() < res_stream_threshold_)
-
- 439 res_body_copy_.swap(res.body);
- 440 buffers_.emplace_back(res_body_copy_.data(), res_body_copy_.size());
-
-
-
- 444 if (need_to_start_read_after_complete_)
-
- 446 need_to_start_read_after_complete_ =
false;
-
-
-
-
-
-
- 453 asio::write(adaptor_.socket(), buffers_);
- 454 cancel_deadline_timer();
- 455 if (res.body.length() > 0)
-
- 457 std::vector<asio::const_buffer> buffers{1};
- 458 const uint8_t* data =
reinterpret_cast<const uint8_t*
>(res.body.data());
- 459 size_t length = res.body.length();
- 460 for (
size_t transferred = 0; transferred < length;)
-
- 462 size_t to_transfer = CROW_MIN(16384UL, length - transferred);
- 463 buffers[0] = asio::const_buffer(data + transferred, to_transfer);
- 464 do_write_sync(buffers);
- 465 transferred += to_transfer;
-
-
- 468 if (close_connection_)
-
- 470 adaptor_.shutdown_readwrite();
-
- 472 CROW_LOG_DEBUG <<
this <<
" from write (res_stream)";
-
-
-
-
-
-
-
-
-
-
-
- 484 auto self = this->shared_from_this();
- 485 adaptor_.socket().async_read_some(
- 486 asio::buffer(buffer_),
- 487 [
self](
const error_code& ec, std::size_t bytes_transferred) {
- 488 bool error_while_reading =
true;
-
-
- 491 bool ret =
self->parser_.feed(self->buffer_.data(), bytes_transferred);
- 492 if (ret && self->adaptor_.is_open())
-
- 494 error_while_reading = false;
-
-
-
- 498 if (error_while_reading)
-
- 500 self->cancel_deadline_timer();
- 501 self->parser_.done();
- 502 self->adaptor_.shutdown_read();
- 503 self->adaptor_.close();
- 504 CROW_LOG_DEBUG <<
self <<
" from read(1) with description: \"" << http_errno_description(
static_cast<http_errno
>(self->parser_.http_errno)) <<
'\"';
-
- 506 else if (self->close_connection_)
-
- 508 self->cancel_deadline_timer();
- 509 self->parser_.done();
-
-
- 512 else if (!self->need_to_call_after_handlers_)
-
- 514 self->start_deadline();
-
-
-
-
-
- 520 self->need_to_start_read_after_complete_ =
true;
-
-
-
-
-
-
- 527 auto self = this->shared_from_this();
-
- 529 adaptor_.socket(), buffers_,
- 530 [
self](
const error_code& ec, std::size_t ) {
-
- 532 self->res_body_copy_.clear();
- 533 if (!self->continue_requested)
-
- 535 self->parser_.clear();
-
-
-
- 539 self->continue_requested = false;
-
-
-
-
- 544 if (self->close_connection_)
-
- 546 self->adaptor_.shutdown_write();
- 547 self->adaptor_.close();
- 548 CROW_LOG_DEBUG << self <<
" from write(1)";
-
-
-
-
- 553 CROW_LOG_DEBUG <<
self <<
" from write(2)";
-
-
-
-
- 558 inline void do_write_sync(std::vector<asio::const_buffer>& buffers)
-
-
- 561 asio::write(adaptor_.socket(), buffers, [&](error_code ec, std::size_t) {
-
-
-
-
-
-
- 568 CROW_LOG_ERROR << ec <<
" - happened while sending buffers";
- 569 CROW_LOG_DEBUG << this <<
" from write (sync)(2)";
-
-
-
-
-
- 575 void cancel_deadline_timer()
-
- 577 CROW_LOG_DEBUG <<
this <<
" timer cancelled: " << &task_timer_ <<
' ' << task_id_;
- 578 task_timer_.cancel(task_id_);
-
-
- 581 void start_deadline()
-
- 583 cancel_deadline_timer();
+ 292 {status::OK,
"HTTP/1.1 200 OK\r\n"},
+ 293 {status::CREATED,
"HTTP/1.1 201 Created\r\n"},
+ 294 {status::ACCEPTED,
"HTTP/1.1 202 Accepted\r\n"},
+ 295 {status::NON_AUTHORITATIVE_INFORMATION,
"HTTP/1.1 203 Non-Authoritative Information\r\n"},
+ 296 {status::NO_CONTENT,
"HTTP/1.1 204 No Content\r\n"},
+ 297 {status::RESET_CONTENT,
"HTTP/1.1 205 Reset Content\r\n"},
+ 298 {status::PARTIAL_CONTENT,
"HTTP/1.1 206 Partial Content\r\n"},
+
+ 300 {status::MULTIPLE_CHOICES,
"HTTP/1.1 300 Multiple Choices\r\n"},
+ 301 {status::MOVED_PERMANENTLY,
"HTTP/1.1 301 Moved Permanently\r\n"},
+ 302 {status::FOUND,
"HTTP/1.1 302 Found\r\n"},
+ 303 {status::SEE_OTHER,
"HTTP/1.1 303 See Other\r\n"},
+ 304 {status::NOT_MODIFIED,
"HTTP/1.1 304 Not Modified\r\n"},
+ 305 {status::TEMPORARY_REDIRECT,
"HTTP/1.1 307 Temporary Redirect\r\n"},
+ 306 {status::PERMANENT_REDIRECT,
"HTTP/1.1 308 Permanent Redirect\r\n"},
+
+ 308 {status::BAD_REQUEST,
"HTTP/1.1 400 Bad Request\r\n"},
+ 309 {status::UNAUTHORIZED,
"HTTP/1.1 401 Unauthorized\r\n"},
+ 310 {status::FORBIDDEN,
"HTTP/1.1 403 Forbidden\r\n"},
+ 311 {status::NOT_FOUND,
"HTTP/1.1 404 Not Found\r\n"},
+ 312 {status::METHOD_NOT_ALLOWED,
"HTTP/1.1 405 Method Not Allowed\r\n"},
+ 313 {status::NOT_ACCEPTABLE,
"HTTP/1.1 406 Not Acceptable\r\n"},
+ 314 {status::PROXY_AUTHENTICATION_REQUIRED,
"HTTP/1.1 407 Proxy Authentication Required\r\n"},
+ 315 {status::CONFLICT,
"HTTP/1.1 409 Conflict\r\n"},
+ 316 {status::GONE,
"HTTP/1.1 410 Gone\r\n"},
+ 317 {status::PAYLOAD_TOO_LARGE,
"HTTP/1.1 413 Payload Too Large\r\n"},
+ 318 {status::UNSUPPORTED_MEDIA_TYPE,
"HTTP/1.1 415 Unsupported Media Type\r\n"},
+ 319 {status::RANGE_NOT_SATISFIABLE,
"HTTP/1.1 416 Range Not Satisfiable\r\n"},
+ 320 {status::EXPECTATION_FAILED,
"HTTP/1.1 417 Expectation Failed\r\n"},
+ 321 {status::PRECONDITION_REQUIRED,
"HTTP/1.1 428 Precondition Required\r\n"},
+ 322 {status::TOO_MANY_REQUESTS,
"HTTP/1.1 429 Too Many Requests\r\n"},
+ 323 {status::UNAVAILABLE_FOR_LEGAL_REASONS,
"HTTP/1.1 451 Unavailable For Legal Reasons\r\n"},
+
+ 325 {status::INTERNAL_SERVER_ERROR,
"HTTP/1.1 500 Internal Server Error\r\n"},
+ 326 {status::NOT_IMPLEMENTED,
"HTTP/1.1 501 Not Implemented\r\n"},
+ 327 {status::BAD_GATEWAY,
"HTTP/1.1 502 Bad Gateway\r\n"},
+ 328 {status::SERVICE_UNAVAILABLE,
"HTTP/1.1 503 Service Unavailable\r\n"},
+ 329 {status::GATEWAY_TIMEOUT,
"HTTP/1.1 504 Gateway Timeout\r\n"},
+ 330 {status::VARIANT_ALSO_NEGOTIATES,
"HTTP/1.1 506 Variant Also Negotiates\r\n"},
+
+
+ 333 static const std::string seperator =
": ";
+
+
+ 336 buffers_.reserve(4 * (res.headers.size() + 5) + 3);
+
+ 338 if (!statusCodes.count(res.code))
+
+ 340 CROW_LOG_WARNING <<
this <<
" status code "
+ 341 <<
"(" << res.code <<
")"
+ 342 <<
" not defined, returning 500 instead";
+
+
+
+ 346 auto& status = statusCodes.find(res.code)->second;
+ 347 buffers_.emplace_back(status.data(), status.size());
+
+ 349 if (res.code >= 400 && res.body.empty())
+ 350 res.body = statusCodes[res.code].substr(9);
+
+ 352 for (
auto& kv : res.headers)
+
+ 354 buffers_.emplace_back(kv.first.data(), kv.first.size());
+ 355 buffers_.emplace_back(seperator.data(), seperator.size());
+ 356 buffers_.emplace_back(kv.second.data(), kv.second.size());
+ 357 buffers_.emplace_back(crlf.data(), crlf.size());
+
+
+ 360 if (!res.manual_length_header && !res.headers.count(
"content-length"))
+
+ 362 content_length_ = std::to_string(res.body.size());
+ 363 static std::string content_length_tag =
"Content-Length: ";
+ 364 buffers_.emplace_back(content_length_tag.data(), content_length_tag.size());
+ 365 buffers_.emplace_back(content_length_.data(), content_length_.size());
+ 366 buffers_.emplace_back(crlf.data(), crlf.size());
+
+ 368 if (!res.headers.count(
"server"))
+
+ 370 static std::string server_tag =
"Server: ";
+ 371 buffers_.emplace_back(server_tag.data(), server_tag.size());
+ 372 buffers_.emplace_back(server_name_.data(), server_name_.size());
+ 373 buffers_.emplace_back(crlf.data(), crlf.size());
+
+ 375 if (!res.headers.count(
"date"))
+
+ 377 static std::string date_tag =
"Date: ";
+ 378 date_str_ = get_cached_date_str();
+ 379 buffers_.emplace_back(date_tag.data(), date_tag.size());
+ 380 buffers_.emplace_back(date_str_.data(), date_str_.size());
+ 381 buffers_.emplace_back(crlf.data(), crlf.size());
+
+
+
+ 385 static std::string keep_alive_tag =
"Connection: Keep-Alive";
+ 386 buffers_.emplace_back(keep_alive_tag.data(), keep_alive_tag.size());
+ 387 buffers_.emplace_back(crlf.data(), crlf.size());
+
+
+ 390 buffers_.emplace_back(crlf.data(), crlf.size());
+
+
+ 393 void do_write_static()
+
+ 395 asio::write(adaptor_.socket(), buffers_);
+
+ 397 if (res.file_info.statResult == 0)
+
+ 399 std::ifstream is(res.file_info.path.c_str(), std::ios::in | std::ios::binary);
+ 400 std::vector<asio::const_buffer> buffers{1};
+
+ 402 is.read(buf,
sizeof(buf));
+ 403 while (is.gcount() > 0)
+
+ 405 buffers[0] = asio::buffer(buf, is.gcount());
+ 406 do_write_sync(buffers);
+ 407 is.read(buf,
sizeof(buf));
+
+
+ 410 if (close_connection_)
+
+ 412 adaptor_.shutdown_readwrite();
+
+ 414 CROW_LOG_DEBUG <<
this <<
" from write (static)";
+
+
+
+
+
+
+
+
+ 423 void do_write_general()
+
+ 425 if (res.body.length() < res_stream_threshold_)
+
+ 427 res_body_copy_.swap(res.body);
+ 428 buffers_.emplace_back(res_body_copy_.data(), res_body_copy_.size());
+
+
+
+ 432 if (need_to_start_read_after_complete_)
+
+ 434 need_to_start_read_after_complete_ =
false;
+
+
+
+
+
+
+ 441 asio::write(adaptor_.socket(), buffers_);
+ 442 cancel_deadline_timer();
+ 443 if (res.body.length() > 0)
+
+ 445 std::vector<asio::const_buffer> buffers{1};
+ 446 const uint8_t* data =
reinterpret_cast<const uint8_t*
>(res.body.data());
+ 447 size_t length = res.body.length();
+ 448 for (
size_t transferred = 0; transferred < length;)
+
+ 450 size_t to_transfer = CROW_MIN(16384UL, length - transferred);
+ 451 buffers[0] = asio::const_buffer(data + transferred, to_transfer);
+ 452 do_write_sync(buffers);
+ 453 transferred += to_transfer;
+
+
+ 456 if (close_connection_)
+
+ 458 adaptor_.shutdown_readwrite();
+
+ 460 CROW_LOG_DEBUG <<
this <<
" from write (res_stream)";
+
+
+
+
+
+
+
+
+
+
+
+ 472 auto self = this->shared_from_this();
+ 473 adaptor_.socket().async_read_some(
+ 474 asio::buffer(buffer_),
+ 475 [
self](
const error_code& ec, std::size_t bytes_transferred) {
+ 476 bool error_while_reading =
true;
+
+
+ 479 bool ret =
self->parser_.feed(self->buffer_.data(), bytes_transferred);
+ 480 if (ret && self->adaptor_.is_open())
+
+ 482 error_while_reading = false;
+
+
+
+ 486 if (error_while_reading)
+
+ 488 self->cancel_deadline_timer();
+ 489 self->parser_.done();
+ 490 self->adaptor_.shutdown_read();
+ 491 self->adaptor_.close();
+ 492 CROW_LOG_DEBUG <<
self <<
" from read(1) with description: \"" << http_errno_description(
static_cast<http_errno
>(self->parser_.http_errno)) <<
'\"';
+
+ 494 else if (self->close_connection_)
+
+ 496 self->cancel_deadline_timer();
+ 497 self->parser_.done();
+
+
+ 500 else if (!self->need_to_call_after_handlers_)
+
+ 502 self->start_deadline();
+
+
+
+
+
+ 508 self->need_to_start_read_after_complete_ =
true;
+
+
+
+
+
+
+ 515 auto self = this->shared_from_this();
+
+ 517 adaptor_.socket(), buffers_,
+ 518 [
self](
const error_code& ec, std::size_t ) {
+
+ 520 self->res_body_copy_.clear();
+ 521 if (!self->continue_requested)
+
+ 523 self->parser_.clear();
+
+
+
+ 527 self->continue_requested = false;
+
+
+
+
+ 532 if (self->close_connection_)
+
+ 534 self->adaptor_.shutdown_write();
+ 535 self->adaptor_.close();
+ 536 CROW_LOG_DEBUG << self <<
" from write(1)";
+
+
+
+
+ 541 CROW_LOG_DEBUG <<
self <<
" from write(2)";
+
+
+
+
+ 546 inline void do_write_sync(std::vector<asio::const_buffer>& buffers)
+
+
+ 549 asio::write(adaptor_.socket(), buffers, [&](error_code ec, std::size_t) {
+
+
+
+
+
+
+ 556 CROW_LOG_ERROR << ec <<
" - happened while sending buffers";
+ 557 CROW_LOG_DEBUG << this <<
" from write (sync)(2)";
+
+
+
+
+
+ 563 void cancel_deadline_timer()
+
+ 565 CROW_LOG_DEBUG <<
this <<
" timer cancelled: " << &task_timer_ <<
' ' << task_id_;
+ 566 task_timer_.cancel(task_id_);
+
+
+ 569 void start_deadline()
+
+ 571 cancel_deadline_timer();
+
+ 573 auto self = this->shared_from_this();
+ 574 task_id_ = task_timer_.schedule([
self] {
+ 575 if (!self->adaptor_.is_open())
+
+
+
+ 579 self->adaptor_.shutdown_readwrite();
+ 580 self->adaptor_.close();
+
+ 582 CROW_LOG_DEBUG <<
this <<
" timer added: " << &task_timer_ <<
' ' << task_id_;
+
- 585 auto self = this->shared_from_this();
- 586 task_id_ = task_timer_.schedule([
self] {
- 587 if (!self->adaptor_.is_open())
-
-
-
- 591 self->adaptor_.shutdown_readwrite();
- 592 self->adaptor_.close();
-
- 594 CROW_LOG_DEBUG <<
this <<
" timer added: " << &task_timer_ <<
' ' << task_id_;
-
-
-
-
-
+
+
+
+
+ 589 std::array<char, 4096> buffer_;
+
+ 591 HTTPParser<Connection> parser_;
+ 592 std::unique_ptr<routing_handle_result> routing_handle_result_;
+
+
+
+ 596 bool close_connection_ =
false;
+
+ 598 const std::string& server_name_;
+ 599 std::vector<asio::const_buffer> buffers_;
- 601 std::array<char, 4096> buffer_;
-
- 603 HTTPParser<Connection> parser_;
- 604 std::unique_ptr<routing_handle_result> routing_handle_result_;
-
-
-
- 608 bool close_connection_ =
false;
-
- 610 const std::string& server_name_;
- 611 std::vector<asio::const_buffer> buffers_;
-
- 613 std::string content_length_;
- 614 std::string date_str_;
- 615 std::string res_body_copy_;
-
- 617 detail::task_timer::identifier_type task_id_{};
-
- 619 bool continue_requested{};
- 620 bool need_to_call_after_handlers_{};
- 621 bool need_to_start_read_after_complete_{};
- 622 bool add_keep_alive_{};
-
- 624 std::tuple<Middlewares...>* middlewares_;
- 625 detail::context<Middlewares...> ctx_;
-
- 627 std::function<std::string()>& get_cached_date_str;
- 628 detail::task_timer& task_timer_;
-
- 630 size_t res_stream_threshold_;
-
- 632 std::atomic<unsigned int>& queue_length_;
-
-
-
+ 601 std::string content_length_;
+ 602 std::string date_str_;
+ 603 std::string res_body_copy_;
+
+ 605 detail::task_timer::identifier_type task_id_{};
+
+ 607 bool continue_requested{};
+ 608 bool need_to_call_after_handlers_{};
+ 609 bool need_to_start_read_after_complete_{};
+ 610 bool add_keep_alive_{};
+
+ 612 std::tuple<Middlewares...>* middlewares_;
+ 613 detail::context<Middlewares...> ctx_;
+
+ 615 std::function<std::string()>& get_cached_date_str;
+ 616 detail::task_timer& task_timer_;
+
+ 618 size_t res_stream_threshold_;
+
+ 620 std::atomic<unsigned int>& queue_length_;
+
+
+
An HTTP connection.
Definition: http_connection.h:48
void complete_request()
Call the after handle middleware and send the write the response to the connection.
Definition: http_connection.h:217
decltype(std::declval< Adaptor >().raw_socket()) & socket()
The TCP socket on top of which the connection is established.
Definition: http_connection.h:87
diff --git a/master/reference/routing_8h_source.html b/master/reference/routing_8h_source.html
index 1087f3934..7df684ea4 100644
--- a/master/reference/routing_8h_source.html
+++ b/master/reference/routing_8h_source.html
@@ -1563,391 +1563,373 @@
1463 CROW_LOG_INFO <<
"Redirecting to a url with trailing slash: " << req.
url;
-
-
- 1467 if (req.get_header_value(
"Host").empty())
-
-
-
-
-
- 1473 res.
add_header(
"Location", (using_ssl ?
"https://" :
"http://") + req.get_header_value(
"Host") + req.
url +
"/");
-
-
-
-
-
- 1479 CROW_LOG_DEBUG <<
"Matched rule (upgrade) '" << rules[rule_index]->rule_ <<
"' " <<
static_cast<uint32_t
>(req.method) <<
" / " << rules[rule_index]->get_methods();
-
-
-
- 1483 rules[rule_index]->handle_upgrade(req, res, std::move(adaptor));
-
-
-
- 1487 exception_handler_(res);
-
-
-
-
-
- 1493 void get_found_bp(std::vector<uint16_t>& bp_i, std::vector<Blueprint*>& blueprints, std::vector<Blueprint*>& found_bps, uint16_t index = 0)
-
-
-
-
-
-
-
-
-
- 1503 auto verify_prefix = [&bp_i, &index, &blueprints, &found_bps]() {
-
- 1505 bp_i[index] < blueprints.size() &&
- 1506 blueprints[bp_i[index]]->prefix().substr(0, found_bps[index - 1]->prefix().length() + 1).compare(std::string(found_bps[index - 1]->prefix() +
'/')) == 0;
-
- 1508 if (index < bp_i.size())
-
-
- 1511 if (verify_prefix())
-
- 1513 found_bps.push_back(blueprints[bp_i[index]]);
- 1514 get_found_bp(bp_i, found_bps.back()->blueprints_, found_bps, ++index);
-
-
-
- 1518 if (found_bps.size() < 2)
-
-
- 1521 found_bps.push_back(blueprints_[bp_i[index]]);
-
-
-
- 1525 found_bps.pop_back();
- 1526 Blueprint* last_element = found_bps.back();
- 1527 found_bps.push_back(last_element->blueprints_[bp_i[index]]);
-
- 1529 get_found_bp(bp_i, found_bps.back()->blueprints_, found_bps, ++index);
-
-
-
-
-
-
-
-
- 1538 std::vector<Blueprint*> bps_found;
- 1539 get_found_bp(found.blueprint_indices, blueprints_, bps_found);
- 1540 for (
int i = bps_found.size() - 1; i > 0; i--)
-
- 1542 std::vector<uint16_t> bpi = found.blueprint_indices;
- 1543 if (bps_found[i]->catchall_rule().has_handler())
-
-
-
- 1547 bps_found[i]->catchall_rule().handler_(req, res);
-
-
-
- 1551 exception_handler_(res);
-
- 1553 #ifdef CROW_ENABLE_DEBUG
- 1554 return std::string(
"Redirected to Blueprint \"" + bps_found[i]->prefix() +
"\" Catchall rule");
-
- 1556 return std::string();
-
-
-
- 1560 if (catchall_rule_.has_handler())
-
-
-
- 1564 catchall_rule_.handler_(req, res);
-
-
-
- 1568 exception_handler_(res);
-
- 1570 #ifdef CROW_ENABLE_DEBUG
- 1571 return std::string(
"Redirected to global Catchall rule");
-
- 1573 return std::string();
-
-
- 1576 return std::string();
-
-
- 1579 std::unique_ptr<routing_handle_result> handle_initial(
request& req,
response& res)
-
- 1581 HTTPMethod method_actual = req.method;
-
- 1583 std::unique_ptr<routing_handle_result> found{
-
-
- 1586 std::vector<uint16_t>(),
-
- 1588 HTTPMethod::InternalMethodCount)};
-
-
- 1591 if (CROW_UNLIKELY(req.method >= HTTPMethod::InternalMethodCount))
-
- 1593 else if (req.method == HTTPMethod::Head)
-
- 1595 *found = per_methods_[
static_cast<int>(method_actual)].trie.find(req.
url);
-
- 1597 if (!found->rule_index)
-
- 1599 method_actual = HTTPMethod::Get;
- 1600 *found = per_methods_[
static_cast<int>(method_actual)].trie.find(req.
url);
- 1601 if (!found->rule_index)
-
- 1603 CROW_LOG_DEBUG <<
"Cannot match rules " << req.
url;
- 1604 res = response(404);
-
-
-
-
-
-
- 1611 found->method = method_actual;
-
-
- 1614 else if (req.method == HTTPMethod::Options)
-
- 1616 std::string allow =
"OPTIONS, HEAD, ";
-
- 1618 if (req.
url ==
"/*")
-
- 1620 for (
int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
-
- 1622 if (
static_cast<int>(HTTPMethod::Head) == i)
-
-
- 1625 if (!per_methods_[i].trie.is_empty())
-
- 1627 allow += method_name(
static_cast<HTTPMethod
>(i)) +
", ";
-
-
- 1630 allow = allow.substr(0, allow.size() - 2);
- 1631 res = response(204);
-
-
- 1634 found->method = method_actual;
-
-
-
-
- 1639 bool rules_matched =
false;
- 1640 for (
int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
-
- 1642 if (per_methods_[i].trie.find(req.
url).rule_index)
-
- 1644 rules_matched =
true;
-
- 1646 if (
static_cast<int>(HTTPMethod::Head) == i)
-
-
- 1649 allow += method_name(
static_cast<HTTPMethod
>(i)) +
", ";
-
+
+
+
+
+
+ 1470 CROW_LOG_DEBUG <<
"Matched rule (upgrade) '" << rules[rule_index]->rule_ <<
"' " <<
static_cast<uint32_t
>(req.method) <<
" / " << rules[rule_index]->get_methods();
+
+
+
+ 1474 rules[rule_index]->handle_upgrade(req, res, std::move(adaptor));
+
+
+
+ 1478 exception_handler_(res);
+
+
+
+
+
+ 1484 void get_found_bp(std::vector<uint16_t>& bp_i, std::vector<Blueprint*>& blueprints, std::vector<Blueprint*>& found_bps, uint16_t index = 0)
+
+
+
+
+
+
+
+
+
+ 1494 auto verify_prefix = [&bp_i, &index, &blueprints, &found_bps]() {
+
+ 1496 bp_i[index] < blueprints.size() &&
+ 1497 blueprints[bp_i[index]]->prefix().substr(0, found_bps[index - 1]->prefix().length() + 1).compare(std::string(found_bps[index - 1]->prefix() +
'/')) == 0;
+
+ 1499 if (index < bp_i.size())
+
+
+ 1502 if (verify_prefix())
+
+ 1504 found_bps.push_back(blueprints[bp_i[index]]);
+ 1505 get_found_bp(bp_i, found_bps.back()->blueprints_, found_bps, ++index);
+
+
+
+ 1509 if (found_bps.size() < 2)
+
+
+ 1512 found_bps.push_back(blueprints_[bp_i[index]]);
+
+
+
+ 1516 found_bps.pop_back();
+ 1517 Blueprint* last_element = found_bps.back();
+ 1518 found_bps.push_back(last_element->blueprints_[bp_i[index]]);
+
+ 1520 get_found_bp(bp_i, found_bps.back()->blueprints_, found_bps, ++index);
+
+
+
+
+
+
+
+
+ 1529 std::vector<Blueprint*> bps_found;
+ 1530 get_found_bp(found.blueprint_indices, blueprints_, bps_found);
+ 1531 for (
int i = bps_found.size() - 1; i > 0; i--)
+
+ 1533 std::vector<uint16_t> bpi = found.blueprint_indices;
+ 1534 if (bps_found[i]->catchall_rule().has_handler())
+
+
+
+ 1538 bps_found[i]->catchall_rule().handler_(req, res);
+
+
+
+ 1542 exception_handler_(res);
+
+ 1544 #ifdef CROW_ENABLE_DEBUG
+ 1545 return std::string(
"Redirected to Blueprint \"" + bps_found[i]->prefix() +
"\" Catchall rule");
+
+ 1547 return std::string();
+
+
+
+ 1551 if (catchall_rule_.has_handler())
+
+
+
+ 1555 catchall_rule_.handler_(req, res);
+
+
+
+ 1559 exception_handler_(res);
+
+ 1561 #ifdef CROW_ENABLE_DEBUG
+ 1562 return std::string(
"Redirected to global Catchall rule");
+
+ 1564 return std::string();
+
+
+ 1567 return std::string();
+
+
+ 1570 std::unique_ptr<routing_handle_result> handle_initial(
request& req,
response& res)
+
+ 1572 HTTPMethod method_actual = req.method;
+
+ 1574 std::unique_ptr<routing_handle_result> found{
+
+
+ 1577 std::vector<uint16_t>(),
+
+ 1579 HTTPMethod::InternalMethodCount)};
+
+
+ 1582 if (CROW_UNLIKELY(req.method >= HTTPMethod::InternalMethodCount))
+
+ 1584 else if (req.method == HTTPMethod::Head)
+
+ 1586 *found = per_methods_[
static_cast<int>(method_actual)].trie.find(req.
url);
+
+ 1588 if (!found->rule_index)
+
+ 1590 method_actual = HTTPMethod::Get;
+ 1591 *found = per_methods_[
static_cast<int>(method_actual)].trie.find(req.
url);
+ 1592 if (!found->rule_index)
+
+ 1594 CROW_LOG_DEBUG <<
"Cannot match rules " << req.
url;
+ 1595 res = response(404);
+
+
+
+
+
+
+ 1602 found->method = method_actual;
+
+
+ 1605 else if (req.method == HTTPMethod::Options)
+
+ 1607 std::string allow =
"OPTIONS, HEAD, ";
+
+ 1609 if (req.
url ==
"/*")
+
+ 1611 for (
int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
+
+ 1613 if (
static_cast<int>(HTTPMethod::Head) == i)
+
+
+ 1616 if (!per_methods_[i].trie.is_empty())
+
+ 1618 allow += method_name(
static_cast<HTTPMethod
>(i)) +
", ";
+
+
+ 1621 allow = allow.substr(0, allow.size() - 2);
+ 1622 res = response(204);
+
+
+ 1625 found->method = method_actual;
+
+
+
+
+ 1630 bool rules_matched =
false;
+ 1631 for (
int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
+
+ 1633 if (per_methods_[i].trie.find(req.
url).rule_index)
+
+ 1635 rules_matched =
true;
+
+ 1637 if (
static_cast<int>(HTTPMethod::Head) == i)
+
+
+ 1640 allow += method_name(
static_cast<HTTPMethod
>(i)) +
", ";
+
+
+
+
+ 1645 allow = allow.substr(0, allow.size() - 2);
+ 1646 res = response(204);
+
+
+ 1649 found->method = method_actual;
+
-
+
- 1654 allow = allow.substr(0, allow.size() - 2);
- 1655 res = response(204);
-
-
- 1658 found->method = method_actual;
-
-
-
-
- 1663 CROW_LOG_DEBUG <<
"Cannot match rules " << req.
url;
- 1664 res = response(404);
-
-
-
-
-
-
-
- 1672 *found = per_methods_[
static_cast<int>(method_actual)].trie.find(req.
url);
-
- 1674 if (!found->rule_index)
-
- 1676 for (
auto& per_method : per_methods_)
-
- 1678 if (per_method.trie.find(req.
url).rule_index)
-
- 1680 const std::string error_message(
get_error(405, *found, req, res));
- 1681 CROW_LOG_DEBUG <<
"Cannot match method " << req.
url <<
" " << method_name(method_actual) <<
". " << error_message;
-
-
-
-
-
-
- 1688 const std::string error_message(
get_error(404, *found, req, res));
- 1689 CROW_LOG_DEBUG <<
"Cannot match rules " << req.
url <<
". " << error_message;
-
-
-
-
- 1694 found->method = method_actual;
-
-
-
-
- 1699 template<
typename App>
- 1700 void handle(request& req, response& res, routing_handle_result found)
-
- 1702 HTTPMethod method_actual = found.method;
- 1703 auto& rules = per_methods_[
static_cast<int>(method_actual)].rules;
- 1704 unsigned rule_index = found.rule_index;
-
- 1706 if (rule_index >= rules.size())
- 1707 throw std::runtime_error(
"Trie internal structure corrupted!");
+ 1654 CROW_LOG_DEBUG <<
"Cannot match rules " << req.
url;
+ 1655 res = response(404);
+
+
+
+
+
+
+
+ 1663 *found = per_methods_[
static_cast<int>(method_actual)].trie.find(req.
url);
+
+ 1665 if (!found->rule_index)
+
+ 1667 for (
auto& per_method : per_methods_)
+
+ 1669 if (per_method.trie.find(req.
url).rule_index)
+
+ 1671 const std::string error_message(
get_error(405, *found, req, res));
+ 1672 CROW_LOG_DEBUG <<
"Cannot match method " << req.
url <<
" " << method_name(method_actual) <<
". " << error_message;
+
+
+
+
+
+
+ 1679 const std::string error_message(
get_error(404, *found, req, res));
+ 1680 CROW_LOG_DEBUG <<
"Cannot match rules " << req.
url <<
". " << error_message;
+
+
+
+
+ 1685 found->method = method_actual;
+
+
+
+
+ 1690 template<
typename App>
+ 1691 void handle(request& req, response& res, routing_handle_result found)
+
+ 1693 HTTPMethod method_actual = found.method;
+ 1694 auto& rules = per_methods_[
static_cast<int>(method_actual)].rules;
+ 1695 unsigned rule_index = found.rule_index;
+
+ 1697 if (rule_index >= rules.size())
+ 1698 throw std::runtime_error(
"Trie internal structure corrupted!");
+
+ 1700 if (rule_index == RULE_SPECIAL_REDIRECT_SLASH)
+
+ 1702 CROW_LOG_INFO <<
"Redirecting to a url with trailing slash: " << req.url;
+ 1703 res = response(301);
+ 1704 res.add_header(
"Location", req.url +
"/");
+
+
+
- 1709 if (rule_index == RULE_SPECIAL_REDIRECT_SLASH)
-
- 1711 CROW_LOG_INFO <<
"Redirecting to a url with trailing slash: " << req.url;
- 1712 res = response(301);
-
-
- 1715 if (req.get_header_value(
"Host").empty())
-
- 1717 res.add_header(
"Location", req.url +
"/");
-
-
-
- 1721 res.add_header(
"Location", (using_ssl ?
"https://" :
"http://") + req.get_header_value(
"Host") + req.url +
"/");
-
-
-
-
-
- 1727 CROW_LOG_DEBUG <<
"Matched rule '" << rules[rule_index]->rule_ <<
"' " <<
static_cast<uint32_t
>(req.method) <<
" / " << rules[rule_index]->get_methods();
-
-
-
- 1731 auto& rule = rules[rule_index];
- 1732 handle_rule<App>(rule, req, res, found.r_params);
-
-
-
- 1736 exception_handler_(res);
-
-
-
-
-
- 1742 template<
typename App>
- 1743 typename std::enable_if<std::tuple_size<typename App::mw_container_t>::value != 0,
void>::type
-
-
- 1746 if (!rule->mw_indices_.empty())
-
- 1748 auto& ctx = *
reinterpret_cast<typename App::context_t*
>(req.middleware_context);
- 1749 auto& container = *
reinterpret_cast<typename App::mw_container_t*
>(req.middleware_container);
- 1750 detail::middleware_call_criteria_dynamic<false> crit_fwd(rule->mw_indices_.indices());
-
- 1752 auto glob_completion_handler = std::move(res.complete_request_handler_);
- 1753 res.complete_request_handler_ = [] {};
-
- 1755 detail::middleware_call_helper<decltype(crit_fwd),
- 1756 0,
typename App::context_t,
typename App::mw_container_t>(crit_fwd, container, req, res, ctx);
-
-
-
- 1760 glob_completion_handler();
-
-
-
- 1764 res.complete_request_handler_ = [&rule, &ctx, &container, &req, &res, glob_completion_handler] {
- 1765 detail::middleware_call_criteria_dynamic<true> crit_bwd(rule->mw_indices_.indices());
+ 1709 CROW_LOG_DEBUG <<
"Matched rule '" << rules[rule_index]->rule_ <<
"' " <<
static_cast<uint32_t
>(req.method) <<
" / " << rules[rule_index]->get_methods();
+
+
+
+ 1713 auto& rule = rules[rule_index];
+ 1714 handle_rule<App>(rule, req, res, found.r_params);
+
+
+
+ 1718 exception_handler_(res);
+
+
+
+
+
+ 1724 template<
typename App>
+ 1725 typename std::enable_if<std::tuple_size<typename App::mw_container_t>::value != 0,
void>::type
+
+
+ 1728 if (!rule->mw_indices_.empty())
+
+ 1730 auto& ctx = *
reinterpret_cast<typename App::context_t*
>(req.middleware_context);
+ 1731 auto& container = *
reinterpret_cast<typename App::mw_container_t*
>(req.middleware_container);
+ 1732 detail::middleware_call_criteria_dynamic<false> crit_fwd(rule->mw_indices_.indices());
+
+ 1734 auto glob_completion_handler = std::move(res.complete_request_handler_);
+ 1735 res.complete_request_handler_ = [] {};
+
+ 1737 detail::middleware_call_helper<decltype(crit_fwd),
+ 1738 0,
typename App::context_t,
typename App::mw_container_t>(crit_fwd, container, req, res, ctx);
+
+
+
+ 1742 glob_completion_handler();
+
+
+
+ 1746 res.complete_request_handler_ = [&rule, &ctx, &container, &req, &res, glob_completion_handler] {
+ 1747 detail::middleware_call_criteria_dynamic<true> crit_bwd(rule->mw_indices_.indices());
+
+ 1749 detail::after_handlers_call_helper<
+
+ 1751 std::tuple_size<typename App::mw_container_t>::value - 1,
+ 1752 typename App::context_t,
+ 1753 typename App::mw_container_t>(crit_bwd, container, ctx, req, res);
+ 1754 glob_completion_handler();
+
+
+ 1757 rule->handle(req, res, rp);
+
+
+ 1760 template<
typename App>
+ 1761 typename std::enable_if<std::tuple_size<typename App::mw_container_t>::value == 0,
void>::type
+
+
+ 1764 rule->handle(req, res, rp);
+
- 1767 detail::after_handlers_call_helper<
-
- 1769 std::tuple_size<typename App::mw_container_t>::value - 1,
- 1770 typename App::context_t,
- 1771 typename App::mw_container_t>(crit_bwd, container, ctx, req, res);
- 1772 glob_completion_handler();
-
-
- 1775 rule->handle(req, res, rp);
-
-
- 1778 template<
typename App>
- 1779 typename std::enable_if<std::tuple_size<typename App::mw_container_t>::value == 0,
void>::type
-
+
+
+ 1769 for (
int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
+
+ 1771 Trie& trie_ = per_methods_[i].trie;
+ 1772 if (!trie_.is_empty())
+
+ 1774 CROW_LOG_DEBUG << method_name(static_cast<HTTPMethod>(i));
+ 1775 trie_.debug_print();
+
+
+
+
+ 1780 std::vector<Blueprint*>& blueprints()
- 1782 rule->handle(req, res, rp);
+
-
+
- 1787 for (
int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
-
- 1789 Trie& trie_ = per_methods_[i].trie;
- 1790 if (!trie_.is_empty())
-
- 1792 CROW_LOG_DEBUG << method_name(static_cast<HTTPMethod>(i));
- 1793 trie_.debug_print();
-
-
-
-
- 1798 std::vector<Blueprint*>& blueprints()
-
-
-
-
-
-
- 1805 return exception_handler_;
-
-
- 1808 static void default_exception_handler(response& res)
-
-
- 1811 res = response(500);
-
-
-
-
-
- 1817 catch (
const bad_request& e)
-
- 1819 res = response (400);
- 1820 res.body = e.what();
-
- 1822 catch (
const std::exception& e)
-
- 1824 CROW_LOG_ERROR <<
"An uncaught exception occurred: " << e.what();
-
-
-
- 1828 CROW_LOG_ERROR <<
"An uncaught exception occurred. The type was unknown so no information was available.";
-
-
-
-
- 1833 CatchallRule catchall_rule_;
-
-
-
- 1837 std::vector<BaseRule*> rules;
-
-
-
-
-
-
- 1844 std::array<PerMethod, static_cast<int>(HTTPMethod::InternalMethodCount)> per_methods_;
- 1845 std::vector<std::unique_ptr<BaseRule>> all_rules_;
- 1846 std::vector<Blueprint*> blueprints_;
- 1847 std::function<void(
crow::response&)> exception_handler_ = &default_exception_handler;
-
-
+ 1787 return exception_handler_;
+
+
+ 1790 static void default_exception_handler(response& res)
+
+
+ 1793 res = response(500);
+
+
+
+
+
+ 1799 catch (
const bad_request& e)
+
+ 1801 res = response (400);
+ 1802 res.body = e.what();
+
+ 1804 catch (
const std::exception& e)
+
+ 1806 CROW_LOG_ERROR <<
"An uncaught exception occurred: " << e.what();
+
+
+
+ 1810 CROW_LOG_ERROR <<
"An uncaught exception occurred. The type was unknown so no information was available.";
+
+
+
+
+ 1815 CatchallRule catchall_rule_;
+
+
+
+ 1819 std::vector<BaseRule*> rules;
+
+
+
+
+
+
+ 1826 std::array<PerMethod, static_cast<int>(HTTPMethod::InternalMethodCount)> per_methods_;
+ 1827 std::vector<std::unique_ptr<BaseRule>> all_rules_;
+ 1828 std::vector<Blueprint*> blueprints_;
+ 1829 std::function<void(
crow::response&)> exception_handler_ = &default_exception_handler;
+
+
A base class for all rules.
Definition: routing.h:90
A blueprint can be considered a smaller section of a Crow app, specifically where the router is conce...
Definition: routing.h:1114
Definition: routing.h:345
@@ -1955,7 +1937,7 @@
self_t & websocket_max_payload(uint64_t max_payload)
Set the default max payload size for websockets.
Definition: app.h:278
A rule that can change its parameters during runtime.
Definition: routing.h:585
Handles matching requests to existing rules and upgrade requests.
Definition: routing.h:1268
-std::string get_error(unsigned short code, routing_handle_result &found, const request &req, response &res)
Is used to handle errors, you insert the error code, found route, request, and response....
Definition: routing.h:1535
+std::string get_error(unsigned short code, routing_handle_result &found, const request &req, response &res)
Is used to handle errors, you insert the error code, found route, request, and response....
Definition: routing.h:1526
Default rule created when CROW_ROUTE is called.
Definition: routing.h:662
A search tree.
Definition: routing.h:726
bool is_empty()
Check whether or not the trie is empty.
Definition: routing.h:760