xref: /trafficserver/src/tscpp/api/Headers.cc (revision 4cfd5a73)
1 /**
2   Licensed to the Apache Software Foundation (ASF) under one
3   or more contributor license agreements.  See the NOTICE file
4   distributed with this work for additional information
5   regarding copyright ownership.  The ASF licenses this file
6   to you under the Apache License, Version 2.0 (the
7   "License"); you may not use this file except in compliance
8   with the License.  You may obtain a copy of the License at
9 
10       http://www.apache.org/licenses/LICENSE-2.0
11 
12   Unless required by applicable law or agreed to in writing, software
13   distributed under the License is distributed on an "AS IS" BASIS,
14   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   See the License for the specific language governing permissions and
16   limitations under the License.
17  */
18 
19 /**
20  * @file Headers.cc
21  */
22 #include <memory>
23 #include <string>
24 #include <cstring>
25 #include <sstream>
26 #include <cctype>
27 
28 #include "ts/ts.h"
29 #include "tscpp/api/Headers.h"
30 #include "logging_internal.h"
31 #include "tscpp/api/noncopyable.h"
32 
33 using atscppapi::Headers;
34 using atscppapi::HeaderField;
35 using atscppapi::HeaderFieldName;
36 using atscppapi::header_field_iterator;
37 using atscppapi::header_field_value_iterator;
38 
39 using std::string;
40 
41 namespace atscppapi
42 {
HeaderFieldName(const std::string & name)43 HeaderFieldName::HeaderFieldName(const std::string &name)
44 {
45   name_ = name;
46 }
47 
48 HeaderFieldName::operator std::string()
49 {
50   return name_;
51 }
52 
53 HeaderFieldName::operator const char *()
54 {
55   return name_.c_str();
56 }
57 
58 std::string
str()59 HeaderFieldName::str()
60 {
61   return name_;
62 }
63 
64 HeaderFieldName::size_type
length()65 HeaderFieldName::length()
66 {
67   return name_.length();
68 }
69 
70 const char *
c_str()71 HeaderFieldName::c_str()
72 {
73   return name_.c_str();
74 }
75 
76 bool
operator ==(const char * field_name)77 HeaderFieldName::operator==(const char *field_name)
78 {
79   return (::strcasecmp(c_str(), field_name) == 0);
80 }
81 
82 bool
operator ==(const std::string & field_name)83 HeaderFieldName::operator==(const std::string &field_name)
84 {
85   return operator==(field_name.c_str());
86 }
87 
88 bool
operator !=(const char * field_name)89 HeaderFieldName::operator!=(const char *field_name)
90 {
91   return !operator==(field_name);
92 }
93 
94 bool
operator !=(const std::string & field_name)95 HeaderFieldName::operator!=(const std::string &field_name)
96 {
97   return !operator==(field_name.c_str());
98 }
99 
100 /**
101  * @private
102  */
103 struct HeaderFieldValueIteratorState : noncopyable {
104   TSMBuffer hdr_buf_              = nullptr;
105   TSMLoc hdr_loc_                 = nullptr;
106   TSMLoc field_loc_               = nullptr;
107   int index_                      = 0;
108   HeaderFieldValueIteratorState() = default;
109   void
resetatscppapi::HeaderFieldValueIteratorState110   reset(TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc field_loc, int index)
111   {
112     hdr_buf_   = bufp;
113     hdr_loc_   = hdr_loc;
114     field_loc_ = field_loc;
115     index_     = index;
116   }
117 };
118 
header_field_value_iterator(void * bufp,void * hdr_loc,void * field_loc,int index)119 header_field_value_iterator::header_field_value_iterator(void *bufp, void *hdr_loc, void *field_loc, int index)
120 {
121   state_ = new HeaderFieldValueIteratorState();
122   state_->reset(static_cast<TSMBuffer>(bufp), static_cast<TSMLoc>(hdr_loc), static_cast<TSMLoc>(field_loc), index);
123 }
124 
header_field_value_iterator(const header_field_value_iterator & it)125 header_field_value_iterator::header_field_value_iterator(const header_field_value_iterator &it)
126 {
127   state_ = new HeaderFieldValueIteratorState();
128   state_->reset(it.state_->hdr_buf_, it.state_->hdr_loc_, it.state_->field_loc_, it.state_->index_);
129 }
130 
~header_field_value_iterator()131 header_field_value_iterator::~header_field_value_iterator()
132 {
133   delete state_;
134 }
135 
operator *()136 std::string header_field_value_iterator::operator*()
137 {
138   if (state_->index_ >= 0) {
139     int length      = 0;
140     const char *str = TSMimeHdrFieldValueStringGet(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_, state_->index_, &length);
141     if (length && str) {
142       return std::string(str, length);
143     }
144   }
145   return std::string();
146 }
147 
148 header_field_value_iterator &
operator ++()149 header_field_value_iterator::operator++()
150 {
151   ++state_->index_;
152   return *this;
153 }
154 
155 header_field_value_iterator
operator ++(int)156 header_field_value_iterator::operator++(int)
157 {
158   header_field_value_iterator tmp(*this);
159   operator++();
160   return tmp;
161 }
162 
163 bool
operator ==(const header_field_value_iterator & rhs) const164 header_field_value_iterator::operator==(const header_field_value_iterator &rhs) const
165 {
166   return (state_->hdr_buf_ == rhs.state_->hdr_buf_) && (state_->hdr_loc_ == rhs.state_->hdr_loc_) &&
167          (state_->field_loc_ == rhs.state_->field_loc_) && (state_->index_ == rhs.state_->index_);
168 }
169 
170 bool
operator !=(const header_field_value_iterator & rhs) const171 header_field_value_iterator::operator!=(const header_field_value_iterator &rhs) const
172 {
173   return !operator==(rhs);
174 }
175 
176 /**
177  * @private
178  */
179 struct MLocContainer {
180   TSMBuffer hdr_buf_;
181   TSMLoc hdr_loc_;
182   TSMLoc field_loc_;
MLocContaineratscppapi::MLocContainer183   MLocContainer(TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc field_loc) : hdr_buf_(bufp), hdr_loc_(hdr_loc), field_loc_(field_loc) {}
~MLocContaineratscppapi::MLocContainer184   ~MLocContainer()
185   {
186     if (field_loc_ != TS_NULL_MLOC) {
187       TSHandleMLocRelease(hdr_buf_, hdr_loc_, field_loc_);
188     }
189   }
190 };
191 
192 /**
193  * @private
194  */
195 struct HeaderFieldIteratorState {
196   std::shared_ptr<MLocContainer> mloc_container_;
HeaderFieldIteratorStateatscppapi::HeaderFieldIteratorState197   HeaderFieldIteratorState(TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc field_loc)
198     : mloc_container_(new MLocContainer(bufp, hdr_loc, field_loc))
199   {
200   }
201 };
202 
203 HeaderField::~HeaderField() = default;
204 
205 HeaderField::size_type
size() const206 HeaderField::size() const
207 {
208   return TSMimeHdrFieldValuesCount(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_,
209                                    iter_.state_->mloc_container_->field_loc_);
210 }
211 
212 header_field_value_iterator
begin()213 HeaderField::begin()
214 {
215   return header_field_value_iterator(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_,
216                                      iter_.state_->mloc_container_->field_loc_, 0);
217 }
218 
219 header_field_value_iterator
end()220 HeaderField::end()
221 {
222   return header_field_value_iterator(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_,
223                                      iter_.state_->mloc_container_->field_loc_, size());
224 }
225 
226 HeaderFieldName
name() const227 HeaderField::name() const
228 {
229   int length      = 0;
230   const char *str = TSMimeHdrFieldNameGet(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_,
231                                           iter_.state_->mloc_container_->field_loc_, &length);
232   if (str && length) {
233     return std::string(str, length);
234   }
235   return std::string();
236 }
237 
238 std::string
values(const char * join)239 HeaderField::values(const char *join)
240 {
241   std::string ret;
242   for (header_field_value_iterator it = begin(); it != end(); ++it) {
243     if (ret.size()) {
244       ret.append(join);
245     }
246     ret.append(*it);
247   }
248   return ret;
249 }
250 
251 std::string
values(const std::string & join)252 HeaderField::values(const std::string &join)
253 {
254   return values(join.c_str());
255 }
256 
257 std::string
values(const char join)258 HeaderField::values(const char join)
259 {
260   return values(std::string().append(1, join));
261 }
262 
263 std::string
value(const std::string & key,size_type index)264 Headers::value(const std::string &key, size_type index /* = 0 */)
265 {
266   header_field_iterator iter = find(key);
267   if (iter == end()) {
268     return string();
269   }
270   if (index == 0) { // skip for loop
271     return *((*iter).begin());
272   }
273   for (; iter != end(); iter.nextDup()) {
274     if (index < (*iter).size()) {
275       return (*iter)[index];
276     }
277     index -= (*iter).size();
278   }
279   return string();
280 }
281 
282 bool
empty()283 HeaderField::empty()
284 {
285   return (begin() == end());
286 }
287 
288 bool
clear()289 HeaderField::clear()
290 {
291   return (TSMimeHdrFieldValuesClear(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_,
292                                     iter_.state_->mloc_container_->field_loc_) == TS_SUCCESS);
293 }
294 
295 bool
erase(const header_field_value_iterator & it)296 HeaderField::erase(const header_field_value_iterator &it)
297 {
298   return (TSMimeHdrFieldValueDelete(it.state_->hdr_buf_, it.state_->hdr_loc_, it.state_->field_loc_, it.state_->index_) ==
299           TS_SUCCESS);
300 }
301 
302 bool
append(const std::string & value)303 HeaderField::append(const std::string &value)
304 {
305   return append(value.c_str(), value.length());
306 }
307 
308 bool
append(const char * value,int length)309 HeaderField::append(const char *value, int length)
310 {
311   return (TSMimeHdrFieldValueStringInsert(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_,
312                                           iter_.state_->mloc_container_->field_loc_, -1, value, -1) == TS_SUCCESS);
313 }
314 
315 bool
setName(const std::string & str)316 HeaderField::setName(const std::string &str)
317 {
318   return (TSMimeHdrFieldNameSet(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_,
319                                 iter_.state_->mloc_container_->field_loc_, str.c_str(), str.length()) == TS_SUCCESS);
320 }
321 
322 bool
operator ==(const char * field_name) const323 HeaderField::operator==(const char *field_name) const
324 {
325   return (::strcasecmp(name(), field_name) == 0);
326 }
327 
328 bool
operator ==(const std::string & field_name) const329 HeaderField::operator==(const std::string &field_name) const
330 {
331   return operator==(field_name.c_str());
332 }
333 
334 bool
operator !=(const char * field_name) const335 HeaderField::operator!=(const char *field_name) const
336 {
337   return !operator==(field_name);
338 }
339 
340 bool
operator !=(const std::string & field_name) const341 HeaderField::operator!=(const std::string &field_name) const
342 {
343   return !operator==(field_name.c_str());
344 }
345 
346 bool
operator =(const std::string & field_value)347 HeaderField::operator=(const std::string &field_value)
348 {
349   if (!clear()) {
350     return false;
351   }
352 
353   return append(field_value);
354 }
355 
356 bool
operator =(const char * field_value)357 HeaderField::operator=(const char *field_value)
358 {
359   if (!clear()) {
360     return false;
361   }
362 
363   return append(field_value);
364 }
365 
operator [](const int index)366 std::string HeaderField::operator[](const int index)
367 {
368   return *header_field_value_iterator(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_,
369                                       iter_.state_->mloc_container_->field_loc_, index);
370 }
371 
372 std::string
str()373 HeaderField::str()
374 {
375   std::ostringstream oss;
376   oss << (*this);
377   return oss.str();
378 }
379 
380 std::ostream &
operator <<(std::ostream & os,HeaderField & obj)381 operator<<(std::ostream &os, HeaderField &obj)
382 {
383   os << obj.name() << ": ";
384   int count = obj.size();
385   for (HeaderField::iterator it = obj.begin(); it != obj.end(); ++it) {
386     os << (*it);
387     if (--count > 0) {
388       os << ",";
389     }
390   }
391   return os;
392 }
393 
header_field_iterator(void * hdr_buf,void * hdr_loc,void * field_loc)394 header_field_iterator::header_field_iterator(void *hdr_buf, void *hdr_loc, void *field_loc)
395   : state_(
396       new HeaderFieldIteratorState(static_cast<TSMBuffer>(hdr_buf), static_cast<TSMLoc>(hdr_loc), static_cast<TSMLoc>(field_loc)))
397 {
398 }
399 
header_field_iterator(const header_field_iterator & it)400 header_field_iterator::header_field_iterator(const header_field_iterator &it) : state_(new HeaderFieldIteratorState(*it.state_)) {}
401 
402 header_field_iterator &
operator =(const header_field_iterator & rhs)403 header_field_iterator::operator=(const header_field_iterator &rhs)
404 {
405   if (this != &rhs) {
406     delete state_;
407     state_ = new HeaderFieldIteratorState(*rhs.state_);
408   }
409   return *this;
410 }
411 
~header_field_iterator()412 header_field_iterator::~header_field_iterator()
413 {
414   delete state_;
415 }
416 
417 // utility function to use to advance iterators using different functions
418 HeaderFieldIteratorState *
advanceIterator(HeaderFieldIteratorState * state,TSMLoc (* getNextField)(TSMBuffer,TSMLoc,TSMLoc))419 advanceIterator(HeaderFieldIteratorState *state, TSMLoc (*getNextField)(TSMBuffer, TSMLoc, TSMLoc))
420 {
421   if (state->mloc_container_->field_loc_ != TS_NULL_MLOC) {
422     TSMBuffer hdr_buf     = state->mloc_container_->hdr_buf_;
423     TSMLoc hdr_loc        = state->mloc_container_->hdr_loc_;
424     TSMLoc next_field_loc = getNextField(hdr_buf, hdr_loc, state->mloc_container_->field_loc_);
425     delete state;
426     state = new HeaderFieldIteratorState(hdr_buf, hdr_loc, next_field_loc);
427   }
428   return state;
429 }
430 
431 header_field_iterator &
operator ++()432 header_field_iterator::operator++()
433 {
434   state_ = advanceIterator(state_, TSMimeHdrFieldNext);
435   return *this;
436 }
437 
438 header_field_iterator
operator ++(int)439 header_field_iterator::operator++(int)
440 {
441   header_field_iterator tmp(*this);
442   operator++();
443   return tmp;
444 }
445 
446 header_field_iterator &
nextDup()447 header_field_iterator::nextDup()
448 {
449   state_ = advanceIterator(state_, TSMimeHdrFieldNextDup);
450   return *this;
451 }
452 
453 bool
operator ==(const header_field_iterator & rhs) const454 header_field_iterator::operator==(const header_field_iterator &rhs) const
455 {
456   return (state_->mloc_container_->hdr_buf_ == rhs.state_->mloc_container_->hdr_buf_) &&
457          (state_->mloc_container_->hdr_loc_ == rhs.state_->mloc_container_->hdr_loc_) &&
458          (state_->mloc_container_->field_loc_ == rhs.state_->mloc_container_->field_loc_);
459 }
460 
461 bool
operator !=(const header_field_iterator & rhs) const462 header_field_iterator::operator!=(const header_field_iterator &rhs) const
463 {
464   return !operator==(rhs);
465 }
466 
operator *()467 HeaderField header_field_iterator::operator*()
468 {
469   return HeaderField(*this);
470 }
471 
472 /**
473  * @private
474  */
475 struct HeadersState : noncopyable {
476   TSMBuffer hdr_buf_;
477   TSMLoc hdr_loc_;
478   bool self_created_structures_;
HeadersStateatscppapi::HeadersState479   HeadersState()
480   {
481     hdr_buf_                 = TSMBufferCreate();
482     hdr_loc_                 = TSHttpHdrCreate(hdr_buf_);
483     self_created_structures_ = true;
484   }
485   void
resetatscppapi::HeadersState486   reset(TSMBuffer bufp, TSMLoc hdr_loc)
487   {
488     if (self_created_structures_) {
489       TSHandleMLocRelease(hdr_buf_, TS_NULL_MLOC /* no parent */, hdr_loc_);
490       TSMBufferDestroy(hdr_buf_);
491       self_created_structures_ = false;
492     }
493     hdr_buf_ = bufp;
494     hdr_loc_ = hdr_loc;
495   }
~HeadersStateatscppapi::HeadersState496   ~HeadersState() { reset(nullptr, nullptr); }
497 };
498 
Headers()499 Headers::Headers()
500 {
501   state_ = new HeadersState();
502 }
503 
Headers(void * bufp,void * mloc)504 Headers::Headers(void *bufp, void *mloc)
505 {
506   state_ = new HeadersState();
507   reset(bufp, mloc);
508 }
509 
510 void
reset(void * bufp,void * mloc)511 Headers::reset(void *bufp, void *mloc)
512 {
513   state_->reset(static_cast<TSMBuffer>(bufp), static_cast<TSMLoc>(mloc));
514 }
515 
~Headers()516 Headers::~Headers()
517 {
518   delete state_;
519 }
520 
521 bool
isInitialized() const522 Headers::isInitialized() const
523 {
524   return (state_->hdr_buf_ && state_->hdr_loc_);
525 }
526 
527 bool
empty()528 Headers::empty()
529 {
530   return (begin() == end());
531 }
532 
533 Headers::size_type
size() const534 Headers::size() const
535 {
536   return TSMimeHdrFieldsCount(state_->hdr_buf_, state_->hdr_loc_);
537 }
538 
539 Headers::size_type
lengthBytes() const540 Headers::lengthBytes() const
541 {
542   return TSMimeHdrLengthGet(state_->hdr_buf_, state_->hdr_loc_);
543 }
544 
545 header_field_iterator
begin()546 Headers::begin()
547 {
548   return header_field_iterator(state_->hdr_buf_, state_->hdr_loc_, TSMimeHdrFieldGet(state_->hdr_buf_, state_->hdr_loc_, 0));
549 }
550 
551 header_field_iterator
end()552 Headers::end()
553 {
554   return header_field_iterator(state_->hdr_buf_, state_->hdr_loc_, TS_NULL_MLOC);
555 }
556 
557 bool
clear()558 Headers::clear()
559 {
560   return (TSMimeHdrFieldsClear(state_->hdr_buf_, state_->hdr_loc_) == TS_SUCCESS);
561 }
562 
563 bool
erase(const header_field_iterator & it)564 Headers::erase(const header_field_iterator &it)
565 {
566   return (TSMimeHdrFieldDestroy(it.state_->mloc_container_->hdr_buf_, it.state_->mloc_container_->hdr_loc_,
567                                 it.state_->mloc_container_->field_loc_) == TS_SUCCESS);
568 }
569 
570 Headers::size_type
erase(const std::string & key)571 Headers::erase(const std::string &key)
572 {
573   return erase(key.c_str(), key.length());
574 }
575 
576 Headers::size_type
erase(const char * key,int length)577 Headers::erase(const char *key, int length)
578 {
579   header_field_iterator iter = find(key, length);
580   size_type erased_count     = 0;
581   while (iter != end()) {
582     header_field_iterator iter_to_delete = iter;
583     iter.nextDup();
584     erase(iter_to_delete);
585     ++erased_count;
586   }
587   return erased_count;
588 }
589 
590 Headers::size_type
count(const char * key,int length)591 Headers::count(const char *key, int length)
592 {
593   size_type ret_count = 0;
594   for (header_field_iterator it = begin(); it != end(); ++it) {
595     if ((*it).name() == key) {
596       ret_count++;
597     }
598   }
599   return ret_count;
600 }
601 
602 Headers::size_type
count(const std::string & key)603 Headers::count(const std::string &key)
604 {
605   return count(key.c_str(), key.length());
606 }
607 
608 std::string
values(const std::string & key,const char * join)609 Headers::values(const std::string &key, const char *join)
610 {
611   std::string ret;
612   for (header_field_iterator it = find(key); it != end(); it.nextDup()) {
613     if (ret.size()) {
614       ret.append(join);
615     }
616     ret.append((*it).values(join));
617   }
618 
619   return ret;
620 }
621 
622 std::string
values(const std::string & key,const std::string & join)623 Headers::values(const std::string &key, const std::string &join)
624 {
625   return values(key, join.c_str());
626 }
627 
628 std::string
values(const std::string & key,const char join)629 Headers::values(const std::string &key, const char join)
630 {
631   return values(key, std::string().assign(1, join));
632 }
633 
634 header_field_iterator
find(const std::string & key)635 Headers::find(const std::string &key)
636 {
637   return find(key.c_str(), key.length());
638 }
639 
640 header_field_iterator
find(const char * key,int length)641 Headers::find(const char *key, int length)
642 {
643   TSMLoc field_loc = TSMimeHdrFieldFind(state_->hdr_buf_, state_->hdr_loc_, key, length);
644   if (field_loc != TS_NULL_MLOC) {
645     return header_field_iterator(state_->hdr_buf_, state_->hdr_loc_, field_loc);
646   }
647 
648   return end();
649 }
650 
651 Headers::iterator
append(const std::string & key,const std::string & value)652 Headers::append(const std::string &key, const std::string &value)
653 {
654   TSMLoc field_loc = TS_NULL_MLOC;
655 
656   if (TSMimeHdrFieldCreate(state_->hdr_buf_, state_->hdr_loc_, &field_loc) == TS_SUCCESS) {
657     TSMimeHdrFieldNameSet(state_->hdr_buf_, state_->hdr_loc_, field_loc, key.c_str(), key.length());
658     TSMimeHdrFieldAppend(state_->hdr_buf_, state_->hdr_loc_, field_loc);
659     TSMimeHdrFieldValueStringInsert(state_->hdr_buf_, state_->hdr_loc_, field_loc, 0, value.c_str(), value.length());
660     return header_field_iterator(state_->hdr_buf_, state_->hdr_loc_, field_loc);
661   } else {
662     return end();
663   }
664 }
665 
666 Headers::iterator
set(const std::string & key,const std::string & value)667 Headers::set(const std::string &key, const std::string &value)
668 {
669   erase(key);
670   return append(key, value);
671 }
672 
operator [](const std::string & key)673 HeaderField Headers::operator[](const std::string &key)
674 {
675   // In STL fashion if the key doesn't exist it will be added with an empty value.
676   header_field_iterator it = find(key);
677   if (it != end()) {
678     return *it;
679   } else {
680     return *append(key, "");
681   }
682 }
683 
684 std::string
str()685 Headers::str()
686 {
687   std::ostringstream oss;
688   oss << (*this);
689   return oss.str();
690 }
691 
692 std::string
wireStr()693 Headers::wireStr()
694 {
695   string retval;
696   for (auto &&iter : *this) {
697     HeaderField hf = iter;
698     retval += hf.name().str();
699     retval += ": ";
700     retval += hf.values(", ");
701     retval += "\r\n";
702   }
703   return retval;
704 }
705 
706 std::ostream &
operator <<(std::ostream & os,atscppapi::Headers & obj)707 operator<<(std::ostream &os, atscppapi::Headers &obj)
708 {
709   for (header_field_iterator it = obj.begin(); it != obj.end(); ++it) {
710     HeaderField hf = *it;
711     os << hf << std::endl;
712   }
713   return os;
714 }
715 
716 } // namespace atscppapi
717