headers.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "headers.h"
  2. #include "stream.h"
  3. #include <util/generic/strbuf.h>
  4. #include <util/generic/yexception.h>
  5. #include <util/stream/output.h>
  6. #include <util/string/ascii.h>
  7. #include <util/string/cast.h>
  8. #include <util/string/strip.h>
  9. static inline TStringBuf Trim(const char* b, const char* e) noexcept {
  10. return StripString(TStringBuf(b, e));
  11. }
  12. THttpInputHeader::THttpInputHeader(const TStringBuf header) {
  13. size_t pos = header.find(':');
  14. if (pos == TString::npos) {
  15. ythrow THttpParseException() << "can not parse http header(" << TString{header}.Quote() << ")";
  16. }
  17. Name_ = TString(header.cbegin(), header.cbegin() + pos);
  18. Value_ = ::ToString(Trim(header.cbegin() + pos + 1, header.cend()));
  19. }
  20. THttpInputHeader::THttpInputHeader(TString name, TString value)
  21. : Name_(std::move(name))
  22. , Value_(std::move(value))
  23. {
  24. }
  25. void THttpInputHeader::OutTo(IOutputStream* stream) const {
  26. typedef IOutputStream::TPart TPart;
  27. const TPart parts[] = {
  28. TPart(Name_),
  29. TPart(": ", 2),
  30. TPart(Value_),
  31. TPart::CrLf(),
  32. };
  33. stream->Write(parts, sizeof(parts) / sizeof(*parts));
  34. }
  35. THttpHeaders::THttpHeaders(IInputStream* stream) {
  36. TString header;
  37. TString line;
  38. bool rdOk = stream->ReadLine(header);
  39. while (rdOk && !header.empty()) {
  40. rdOk = stream->ReadLine(line);
  41. if (rdOk && ((line[0] == ' ') || (line[0] == '\t'))) {
  42. header += line;
  43. } else {
  44. AddHeader(THttpInputHeader(header));
  45. header = line;
  46. }
  47. }
  48. }
  49. bool THttpHeaders::HasHeader(const TStringBuf header) const {
  50. return FindHeader(header);
  51. }
  52. const THttpInputHeader* THttpHeaders::FindHeader(const TStringBuf header) const {
  53. for (const auto& hdr : Headers_) {
  54. if (AsciiCompareIgnoreCase(hdr.Name(), header) == 0) {
  55. return &hdr;
  56. }
  57. }
  58. return nullptr;
  59. }
  60. void THttpHeaders::RemoveHeader(const TStringBuf header) {
  61. for (auto h = Headers_.begin(); h != Headers_.end(); ++h) {
  62. if (AsciiCompareIgnoreCase(h->Name(), header) == 0) {
  63. Headers_.erase(h);
  64. return;
  65. }
  66. }
  67. }
  68. void THttpHeaders::AddOrReplaceHeader(const THttpInputHeader& header) {
  69. for (auto& hdr : Headers_) {
  70. if (AsciiCompareIgnoreCase(hdr.Name(), header.Name()) == 0) {
  71. hdr = header;
  72. return;
  73. }
  74. }
  75. AddHeader(header);
  76. }
  77. void THttpHeaders::AddHeader(THttpInputHeader header) {
  78. Headers_.push_back(std::move(header));
  79. }
  80. void THttpHeaders::OutTo(IOutputStream* stream) const {
  81. for (TConstIterator header = Begin(); header != End(); ++header) {
  82. header->OutTo(stream);
  83. }
  84. }
  85. template <>
  86. void Out<THttpHeaders>(IOutputStream& out, const THttpHeaders& h) {
  87. h.OutTo(&out);
  88. }