| 109 | |
| 110 | template <typename T, typename W> |
| 111 | TString BuildRequest(const NNeh::TParsedLocation& loc, const T& urlParams, const TStringBuf headers, const W& content, const TStringBuf contentType, ERequestType requestType, NNeh::NHttp::ERequestFlags requestFlags) { |
| 112 | const bool isAbsoluteUri = requestFlags.HasFlags(NNeh::NHttp::ERequestFlag::AbsoluteUri); |
| 113 | |
| 114 | const auto contentLength = GetLength(content); |
| 115 | TStringStream out; |
| 116 | out.Reserve(loc.Service.length() + loc.Host.length() + GetLength(urlParams) + headers.length() + contentType.length() + contentLength + (isAbsoluteUri ? (loc.Host.length() + 13) : 0) // 13 - is a max port number length + scheme length |
| 117 | + 96); //just some extra space |
| 118 | |
| 119 | Y_ASSERT(requestType != ERequestType::Any); |
| 120 | out << requestType; |
| 121 | out << ' '; |
| 122 | if (isAbsoluteUri) { |
| 123 | out << loc.Scheme << TStringBuf("://") << loc.Host; |
| 124 | if (loc.Port) { |
| 125 | out << ':' << loc.Port; |
| 126 | } |
| 127 | } |
| 128 | out << '/' << loc.Service; |
| 129 | |
| 130 | WriteUrl(urlParams, out); |
| 131 | out << TStringBuf(" HTTP/1.1\r\n"); |
| 132 | |
| 133 | NNeh::NHttp::WriteHostHeaderIfNot(out, loc.Host, loc.Port, headers); |
| 134 | SafeWriteHeaders(out, headers); |
| 135 | if (!IsEmpty(content)) { |
| 136 | if (!!contentType && headers.find(TStringBuf("Content-Type:")) == TString::npos) { |
| 137 | out << TStringBuf("Content-Type: ") << contentType << TStringBuf("\r\n"); |
| 138 | } |
| 139 | out << TStringBuf("Content-Length: ") << contentLength << TStringBuf("\r\n"); |
| 140 | out << TStringBuf("\r\n"); |
| 141 | WriteImpl(content, out); |
| 142 | } else { |
| 143 | out << TStringBuf("\r\n"); |
| 144 | } |
| 145 | return out.Str(); |
| 146 | } |
| 147 | |
| 148 | bool NeedGetRequestFor(TStringBuf scheme) { |
| 149 | return scheme == schemeHttp2 || scheme == schemeHttp || scheme == schemeHttps || scheme == schemeHttpUnix; |
no test coverage detected