1 /** @file
2 
3     Plugin to perform background fetches of certain content that would
4     otherwise not be cached. For example, Range: requests / responses.
5 
6     @section license License
7 
8     Licensed to the Apache Software Foundation (ASF) under one
9     or more contributor license agreements.  See the NOTICE file
10     distributed with this work for additional information
11     regarding copyright ownership.  The ASF licenses this file
12     to you under the Apache License, Version 2.0 (the
13     "License"); you may not use this file except in compliance
14     with the License.  You may obtain a copy of the License at
15 
16     http://www.apache.org/licenses/LICENSE-2.0
17 
18     Unless required by applicable law or agreed to in writing, software
19     distributed under the License is distributed on an "AS IS" BASIS,
20     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21     See the License for the specific language governing permissions and
22     limitations under the License.
23 */
24 #include <cstdlib>
25 
26 #include "configs.h"
27 #include "headers.h"
28 
29 ///////////////////////////////////////////////////////////////////////////
30 // Remove a header (fully) from an TSMLoc / TSMBuffer. Return the number
31 // of fields (header values) we removed.
32 int
remove_header(TSMBuffer bufp,TSMLoc hdr_loc,const char * header,int len)33 remove_header(TSMBuffer bufp, TSMLoc hdr_loc, const char *header, int len)
34 {
35   TSMLoc field = TSMimeHdrFieldFind(bufp, hdr_loc, header, len);
36   int cnt      = 0;
37 
38   while (field) {
39     TSMLoc tmp = TSMimeHdrFieldNextDup(bufp, hdr_loc, field);
40 
41     ++cnt;
42     TSMimeHdrFieldDestroy(bufp, hdr_loc, field);
43     TSHandleMLocRelease(bufp, hdr_loc, field);
44     field = tmp;
45   }
46 
47   return cnt;
48 }
49 
50 ///////////////////////////////////////////////////////////////////////////
51 // Set a header to a specific value. This will avoid going to through a
52 // remove / add sequence in case of an existing header.
53 // but clean.
54 bool
set_header(TSMBuffer bufp,TSMLoc hdr_loc,const char * header,int len,const char * val,int val_len)55 set_header(TSMBuffer bufp, TSMLoc hdr_loc, const char *header, int len, const char *val, int val_len)
56 {
57   if (!bufp || !hdr_loc || !header || len <= 0 || !val || val_len <= 0) {
58     return false;
59   }
60 
61   bool ret         = false;
62   TSMLoc field_loc = TSMimeHdrFieldFind(bufp, hdr_loc, header, len);
63 
64   if (!field_loc) {
65     // No existing header, so create one
66     if (TS_SUCCESS == TSMimeHdrFieldCreateNamed(bufp, hdr_loc, header, len, &field_loc)) {
67       if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, val, val_len)) {
68         TSMimeHdrFieldAppend(bufp, hdr_loc, field_loc);
69         ret = true;
70       }
71       TSHandleMLocRelease(bufp, hdr_loc, field_loc);
72     }
73   } else {
74     TSMLoc tmp = nullptr;
75     bool first = true;
76 
77     while (field_loc) {
78       if (first) {
79         first = false;
80         if (TS_SUCCESS == TSMimeHdrFieldValueStringSet(bufp, hdr_loc, field_loc, -1, val, val_len)) {
81           ret = true;
82         }
83       } else {
84         TSMimeHdrFieldDestroy(bufp, hdr_loc, field_loc);
85       }
86       tmp = TSMimeHdrFieldNextDup(bufp, hdr_loc, field_loc);
87       TSHandleMLocRelease(bufp, hdr_loc, field_loc);
88       field_loc = tmp;
89     }
90   }
91 
92   return ret;
93 }
94 
95 ///////////////////////////////////////////////////////////////////////////
96 // Dump a header on stderr, useful together with TSDebug().
97 void
dump_headers(TSMBuffer bufp,TSMLoc hdr_loc)98 dump_headers(TSMBuffer bufp, TSMLoc hdr_loc)
99 {
100   TSIOBuffer output_buffer;
101   TSIOBufferReader reader;
102   TSIOBufferBlock block;
103   int64_t block_avail;
104 
105   output_buffer = TSIOBufferCreate();
106   reader        = TSIOBufferReaderAlloc(output_buffer);
107 
108   /* This will print  just MIMEFields and not the http request line */
109   TSMimeHdrPrint(bufp, hdr_loc, output_buffer);
110 
111   /* We need to loop over all the buffer blocks, there can be more than 1 */
112   block = TSIOBufferReaderStart(reader);
113   do {
114     const char *block_start = TSIOBufferBlockReadStart(block, reader, &block_avail);
115     if (block_avail > 0) {
116       TSDebug(PLUGIN_NAME, "Headers are:\n%.*s", static_cast<int>(block_avail), block_start);
117     }
118     TSIOBufferReaderConsume(reader, block_avail);
119     block = TSIOBufferReaderStart(reader);
120   } while (block && block_avail != 0);
121 
122   /* Free up the TSIOBuffer that we used to print out the header */
123   TSIOBufferReaderFree(reader);
124   TSIOBufferDestroy(output_buffer);
125 }
126