called non thread-safe (from outside thread)
| 1679 | |
| 1680 | //called non thread-safe (from outside thread) |
| 1681 | void SendError(TAtomicBase requestId, unsigned httpCode, const TString& descr, const THttpVersion& ver, const TString& headers) { |
| 1682 | if (Canceled_) { |
| 1683 | return; |
| 1684 | } |
| 1685 | |
| 1686 | class THttpErrorResponseFormatter { |
| 1687 | public: |
| 1688 | THttpErrorResponseFormatter(unsigned theHttpCode, const TString& theDescr, const THttpVersion& theVer, bool closeConnection, const TString& headers) { |
| 1689 | PrintHttpVersion(Answer, theVer); |
| 1690 | Answer << TStringBuf(" ") << theHttpCode << TStringBuf(" "); |
| 1691 | if (theDescr.size() && !THttp2Options::ErrorDetailsAsResponseBody) { |
| 1692 | // Reason-Phrase = *<TEXT, excluding CR, LF> |
| 1693 | // replace bad chars to '.' |
| 1694 | TString reasonPhrase = theDescr; |
| 1695 | for (TString::iterator it = reasonPhrase.begin(); it != reasonPhrase.end(); ++it) { |
| 1696 | char& ch = *it; |
| 1697 | if (ch == ' ') { |
| 1698 | continue; |
| 1699 | } |
| 1700 | if (((ch & 31) == ch) || static_cast<unsigned>(ch) == 127 || (static_cast<unsigned>(ch) & 0x80)) { |
| 1701 | //CTLs || DEL(127) || non ascii |
| 1702 | // (ch <= 32) || (ch >= 127) |
| 1703 | ch = '.'; |
| 1704 | } |
| 1705 | } |
| 1706 | Answer << reasonPhrase; |
| 1707 | } else { |
| 1708 | Answer << HttpCodeStr(static_cast<int>(theHttpCode)); |
| 1709 | } |
| 1710 | |
| 1711 | if (closeConnection) { |
| 1712 | Answer << TStringBuf("\r\nConnection: close"); |
| 1713 | } |
| 1714 | |
| 1715 | if (headers) { |
| 1716 | Answer << "\r\n" << headers; |
| 1717 | } |
| 1718 | |
| 1719 | if (THttp2Options::ErrorDetailsAsResponseBody) { |
| 1720 | Answer << TStringBuf("\r\nContent-Length:") << theDescr.size() << "\r\n\r\n" << theDescr; |
| 1721 | } else { |
| 1722 | Answer << "\r\n" |
| 1723 | "Content-Length:0\r\n\r\n"sv; |
| 1724 | } |
| 1725 | |
| 1726 | Parts[0].buf = Answer.Data(); |
| 1727 | Parts[0].len = Answer.Size(); |
| 1728 | } |
| 1729 | |
| 1730 | TStringStream Answer; |
| 1731 | IOutputStream::TPart Parts[1]; |
| 1732 | }; |
| 1733 | |
| 1734 | class TBuffers: public THttpErrorResponseFormatter, public TTcpSocket::IBuffers { |
| 1735 | public: |
| 1736 | TBuffers( |
| 1737 | unsigned theHttpCode, |
| 1738 | const TString& theDescr, |