| 276 | } |
| 277 | |
| 278 | bool THttpParser::DecodeContent(TString& decodedContent) const { |
| 279 | if (!ContentEncoding_ || ContentEncoding_ == "identity" || ContentEncoding_ == "none") { |
| 280 | decodedContent = Content_; |
| 281 | return false; |
| 282 | } |
| 283 | |
| 284 | TMemoryInput in(Content_.data(), Content_.size()); |
| 285 | if (ContentEncoding_ == "gzip") { |
| 286 | auto decompressor = TZLibDecompress(&in, ZLib::GZip); |
| 287 | if (!GzipAllowMultipleStreams_) { |
| 288 | decompressor.SetAllowMultipleStreams(false); |
| 289 | } |
| 290 | decodedContent = decompressor.ReadAll(); |
| 291 | } else if (ContentEncoding_ == "deflate") { |
| 292 | |
| 293 | //https://tools.ietf.org/html/rfc1950 |
| 294 | bool definitelyNoZlibHeader; |
| 295 | if (Content_.size() < 2) { |
| 296 | definitelyNoZlibHeader = true; |
| 297 | } else { |
| 298 | const ui16 cmf = static_cast<ui8>(Content_[0]); |
| 299 | const ui16 flg = static_cast<ui8>(Content_[1]); |
| 300 | definitelyNoZlibHeader = ((cmf << 8) | flg) % 31 != 0; |
| 301 | } |
| 302 | |
| 303 | try { |
| 304 | decodedContent = TZLibDecompress(&in, definitelyNoZlibHeader ? ZLib::Raw : ZLib::ZLib).ReadAll(); |
| 305 | } |
| 306 | catch(...) { |
| 307 | if (definitelyNoZlibHeader) { |
| 308 | throw; |
| 309 | } |
| 310 | TMemoryInput retryInput(Content_.data(), Content_.size()); |
| 311 | decodedContent = TZLibDecompress(&retryInput, ZLib::Raw).ReadAll(); |
| 312 | } |
| 313 | } else if (ContentEncoding_.StartsWith("z-")) { |
| 314 | // opposite for library/cpp/http/io/stream.h |
| 315 | const NBlockCodecs::ICodec* codec = nullptr; |
| 316 | try { |
| 317 | const TStringBuf codecName = TStringBuf(ContentEncoding_).SubStr(2); |
| 318 | if (codecName.StartsWith("zstd06") || codecName.StartsWith("zstd08")) { |
| 319 | ythrow NBlockCodecs::TNotFound() << codecName; |
| 320 | } |
| 321 | codec = NBlockCodecs::Codec(codecName); |
| 322 | } catch(const NBlockCodecs::TNotFound& exc) { |
| 323 | throw THttpParseException() << "Unsupported content-encoding method: " << exc.AsStrBuf(); |
| 324 | } |
| 325 | NBlockCodecs::TDecodedInput decoder(&in, codec); |
| 326 | decodedContent = decoder.ReadAll(); |
| 327 | } else if (ContentEncoding_ == "lz4") { |
| 328 | const auto* codec = NBlockCodecs::Codec(TStringBuf(ContentEncoding_)); |
| 329 | decodedContent = codec->Decode(Content_); |
| 330 | } else if (ContentEncoding_ == "br") { |
| 331 | TBrotliDecompress decoder(&in); |
| 332 | decodedContent = decoder.ReadAll(); |
| 333 | } else { |
| 334 | throw THttpParseException() << "Unsupported content-encoding method: " << ContentEncoding_; |
| 335 | } |
no test coverage detected