| 852 | } |
| 853 | |
| 854 | void HTTPHandler::trySendExceptionToClient( |
| 855 | const std::string & s, int exception_code, HTTPServerRequest & request, HTTPServerResponse & response, Output & used_output) |
| 856 | { |
| 857 | try |
| 858 | { |
| 859 | response.set("X-ClickHouse-Exception-Code", toString<int>(exception_code)); |
| 860 | |
| 861 | /// FIXME: make sure that no one else is reading from the same stream at the moment. |
| 862 | |
| 863 | /// If HTTP method is POST and Keep-Alive is turned on, we should read the whole request body |
| 864 | /// to avoid reading part of the current request body in the next request. |
| 865 | if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST |
| 866 | && response.getKeepAlive() |
| 867 | && exception_code != ErrorCodes::HTTP_LENGTH_REQUIRED |
| 868 | && !request.getStream().eof()) |
| 869 | { |
| 870 | request.getStream().ignoreAll(); |
| 871 | } |
| 872 | |
| 873 | if (exception_code == ErrorCodes::REQUIRED_PASSWORD) |
| 874 | { |
| 875 | response.requireAuthentication("ClickHouse server HTTP API"); |
| 876 | } |
| 877 | else |
| 878 | { |
| 879 | response.setStatusAndReason(exceptionCodeToHTTPStatus(exception_code)); |
| 880 | } |
| 881 | |
| 882 | if (!response.sent() && !used_output.out_maybe_compressed) |
| 883 | { |
| 884 | /// If nothing was sent yet and we don't even know if we must compress the response. |
| 885 | *response.send() << s << std::endl; |
| 886 | } |
| 887 | else if (used_output.out_maybe_compressed) |
| 888 | { |
| 889 | /// Destroy CascadeBuffer to actualize buffers' positions and reset extra references |
| 890 | if (used_output.hasDelayed()) |
| 891 | used_output.out_maybe_delayed_and_compressed.reset(); |
| 892 | |
| 893 | /// Send the error message into already used (and possibly compressed) stream. |
| 894 | /// Note that the error message will possibly be sent after some data. |
| 895 | /// Also HTTP code 200 could have already been sent. |
| 896 | |
| 897 | /// If buffer has data, and that data wasn't sent yet, then no need to send that data |
| 898 | bool data_sent = used_output.out->count() != used_output.out->offset(); |
| 899 | |
| 900 | if (!data_sent) |
| 901 | { |
| 902 | used_output.out_maybe_compressed->position() = used_output.out_maybe_compressed->buffer().begin(); |
| 903 | used_output.out->position() = used_output.out->buffer().begin(); |
| 904 | } |
| 905 | |
| 906 | writeString(s, *used_output.out_maybe_compressed); |
| 907 | writeChar('\n', *used_output.out_maybe_compressed); |
| 908 | |
| 909 | used_output.out_maybe_compressed->next(); |
| 910 | used_output.out->finalize(); |
| 911 | } |
nothing calls this directly
no test coverage detected