headers.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. THttpHeaders::THttpHeaders(TArrayRef<const THttpInputHeader> headers) {
  50. for (const auto& header : headers) {
  51. AddHeader(header);
  52. }
  53. }
  54. bool THttpHeaders::HasHeader(const TStringBuf header) const {
  55. return FindHeader(header);
  56. }
  57. const THttpInputHeader* THttpHeaders::FindHeader(const TStringBuf header) const {
  58. for (const auto& hdr : Headers_) {
  59. if (AsciiEqualsIgnoreCase(hdr.Name(), header)) {
  60. return &hdr;
  61. }
  62. }
  63. return nullptr;
  64. }
  65. void THttpHeaders::RemoveHeader(const TStringBuf header) {
  66. for (auto h = Headers_.begin(); h != Headers_.end(); ++h) {
  67. if (AsciiEqualsIgnoreCase(h->Name(), header)) {
  68. Headers_.erase(h);
  69. return;
  70. }
  71. }
  72. }
  73. void THttpHeaders::AddOrReplaceHeader(const THttpInputHeader& header) {
  74. TStringBuf name = header.Name();
  75. for (auto& hdr : Headers_) {
  76. if (AsciiEqualsIgnoreCase(hdr.Name(), name)) {
  77. hdr = header;
  78. return;
  79. }
  80. }
  81. AddHeader(header);
  82. }
  83. void THttpHeaders::AddHeader(THttpInputHeader header) {
  84. Headers_.push_back(std::move(header));
  85. }
  86. void THttpHeaders::OutTo(IOutputStream* stream) const {
  87. for (TConstIterator header = Begin(); header != End(); ++header) {
  88. header->OutTo(stream);
  89. }
  90. }
  91. template <>
  92. void Out<THttpHeaders>(IOutputStream& out, const THttpHeaders& h) {
  93. h.OutTo(&out);
  94. }