| 654 | } |
| 655 | |
| 656 | bool HTTPHandler::trySendExceptionToClient( |
| 657 | int exception_code, const std::string & message, HTTPServerRequest & request, HTTPServerResponse & response, Output & used_output) |
| 658 | try |
| 659 | { |
| 660 | if (!used_output.out_holder && !used_output.exception_is_written) |
| 661 | { |
| 662 | /// If nothing was sent yet and we don't even know if we must compress the response. |
| 663 | auto wb = WriteBufferFromHTTPServerResponse(response, request.getMethod() == HTTPRequest::HTTP_HEAD); |
| 664 | return wb.cancelWithException(request, exception_code, message, nullptr); |
| 665 | } |
| 666 | |
| 667 | chassert(used_output.out_maybe_compressed); |
| 668 | |
| 669 | /// Destroy CascadeBuffer to actualize buffers' positions and reset extra references |
| 670 | if (used_output.hasDelayed()) |
| 671 | { |
| 672 | /// do not call finalize here for CascadeWriteBuffer used_output.out_maybe_delayed_and_compressed, |
| 673 | /// exception is written into used_output.out_maybe_compressed later |
| 674 | auto write_buffers = used_output.out_delayed_and_compressed_holder->getResultBuffers(); |
| 675 | /// cancel the rest unused buffers |
| 676 | for (auto & wb : write_buffers) |
| 677 | if (isSharedPtrUnique(wb)) |
| 678 | wb->cancel(); |
| 679 | |
| 680 | used_output.out_maybe_delayed_and_compressed = used_output.out_maybe_compressed; |
| 681 | used_output.out_delayed_and_compressed_holder.reset(); |
| 682 | } |
| 683 | |
| 684 | if (used_output.exception_is_written) |
| 685 | { |
| 686 | LOG_TRACE(log, "Exception has already been written to output format by current output formatter, nothing to do"); |
| 687 | /// everything has been held by output format write |
| 688 | return true; |
| 689 | } |
| 690 | |
| 691 | /// We might have special formatter for exception message. |
| 692 | if (used_output.exception_writer) |
| 693 | { |
| 694 | used_output.exception_writer(*used_output.out_maybe_compressed, exception_code, message); |
| 695 | return true; |
| 696 | } |
| 697 | |
| 698 | /// This is the worst case scenario |
| 699 | /// There is no support from output_format. |
| 700 | /// output_format either did not faced the exception or did not support the exception writing |
| 701 | |
| 702 | /// Send the error message into already used (and possibly compressed) stream. |
| 703 | /// Note that the error message will possibly be sent after some data. |
| 704 | /// Also HTTP code 200 could have already been sent. |
| 705 | return used_output.out_holder->cancelWithException(request, exception_code, message, used_output.out_maybe_compressed.get()); |
| 706 | } |
| 707 | catch (...) |
| 708 | { |
| 709 | /// The message could be not sent due to error on allocations |
| 710 | /// or due to exception in used_output.exception_writer |
| 711 | /// or because the socket is broken |
| 712 | tryLogCurrentException(log, "Cannot send exception to client"); |
| 713 | return false; |
nothing calls this directly
no test coverage detected