bes  Updated for version 3.20.8
EffectiveUrl.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 //
3 // EffectiveUrl.cc
4 // This file is part of the BES http package, part of the Hyrax data server.
5 
6 // Copyright (c) 2020 OPeNDAP, Inc.
7 // Author: Nathan Potter <ndp@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 // Authors:
26 // ndp Nathan Potter <ndp@opendap.org>
27 
28 #include "config.h"
29 
30 #include <string>
31 #include <sstream>
32 #include <map>
33 #include <vector>
34 
35 #include <time.h>
36 
37 #include "BESDebug.h"
38 #include "BESUtil.h"
39 #include "BESLog.h"
40 
41 #include "HttpNames.h"
42 #include "url_impl.h"
43 #include "EffectiveUrl.h"
44 
45 using std::string;
46 using std::map;
47 using std::pair;
48 using std::vector;
49 using std::endl;
50 using std::stringstream;
51 
52 #define CACHE_CONTROL_HEADER_KEY "cache-control"
53 #define REFRESH_THRESHOLD 60
54 
55 #define MODULE HTTP_MODULE
56 #define prolog std::string("EffectiveUrl::").append(__func__).append("() - ")
57 
58 namespace http {
59 
60 
68 
69  BESDEBUG(MODULE, prolog << "BEGIN" << endl);
70  bool expired = false;
71  bool found = false;
72  string cc_hdr_val;
73 
74  get_header(CACHE_CONTROL_HEADER_KEY, cc_hdr_val, found);
75  if (found) {
76  BESDEBUG(MODULE, prolog << CACHE_CONTROL_HEADER_KEY << " '" << cc_hdr_val << "'" << endl);
77  time_t now;
78  time(&now); /* get current time; same as: timer = time(NULL) */
79  BESDEBUG(MODULE, prolog << "now: " << now << endl);
80 
81  // Example: 'Cache-Control: private, max-age=600'
82  string max_age_key("max-age=");
83  size_t max_age_index = cc_hdr_val.find(max_age_key);
84  if (max_age_index != cc_hdr_val.npos) {
85  string max_age_str = cc_hdr_val.substr(max_age_index + max_age_key.size());
86  time_t max_age;
87  std::istringstream(max_age_str) >> max_age; // Returns 0 if the parse fails.
88  time_t expires = ingest_time() + max_age;
89  time_t remaining = expires - now;
90  BESDEBUG(MODULE, prolog << "expires: " << expires <<
91  " remaining: " << remaining <<
92  " threshold: " << REFRESH_THRESHOLD << endl);
93 
94  expired = remaining < REFRESH_THRESHOLD;
95  BESDEBUG(MODULE, prolog << "expired: " << (expired ? "true" : "false") << endl);
96  }
97  }
98  if (!expired) {
99  expired = url::is_expired();
100  }
101  BESDEBUG(MODULE, prolog << "END expired: " << (expired ? "true" : "false") << endl);
102  return expired;
103  }
104 
105 
106 
107 
115  void EffectiveUrl::get_header(const std::string &name, std::string &value, bool &found ) {
116  found = false;
117  string lc_name = BESUtil::lowercase(name);
118  auto rname_itr = d_response_header_names.rbegin();
119  auto rvalue_itr = d_response_header_values.rbegin();
120  while(!found && rname_itr != d_response_header_names.rend()){
121  string hdr_name = *rname_itr;
122  found = (lc_name == hdr_name);
123  if(found){
124  value = *rvalue_itr;
125  }
126  ++rname_itr;
127  ++rvalue_itr;
128  }
129  }
130 
136  stringstream ss;
137  string indent_inc = " ";
138  string indent = indent_inc;
139 
140  ss << url::dump();
141  auto name_itr = d_response_header_names.begin();
142  auto value_itr = d_response_header_values.begin();
143  while(name_itr!=d_response_header_names.end()){
144  ss << indent << "Header: " << *name_itr << ": " << *value_itr << endl;
145  ++name_itr;
146  ++value_itr;
147  }
148  return ss.str();
149  }
150 
151 
156  void EffectiveUrl::ingest_response_headers(const vector<string> &resp_hdrs)
157  {
158  d_resp_hdr_lines.clear();
159  d_resp_hdr_lines = resp_hdrs;
160  d_response_header_names.clear();
161  d_response_header_values.clear();
162 
163  auto index = resp_hdrs.begin();
164  while(index!=resp_hdrs.end()){
165  size_t colon = (*index).find(":");
166  if(colon!=(*index).npos){
167  string key((*index).substr(0,colon));
168  key = BESUtil::lowercase(key);
169  string value((*index).substr(colon));
170  d_response_header_names.push_back(key);
171  d_response_header_values.push_back(value);
172  BESDEBUG(MODULE, prolog << "Ingested header: " << key << ": " << value << "(size: " << d_response_header_values.size() << ")" << endl);
173  }
174  else {
175  ERROR_LOG(prolog << "Encounter malformed response header! Missing ':' delimiter. SKIPPING" << endl);
176  }
177  index++;
178  }
179  }
180 
181 
182 
183 
184 } // namespace http
static std::string lowercase(const std::string &s)
Definition: BESUtil.cc:200
std::string dump() override
A string dump of the instance.
bool is_expired() override
Returns true if URL is reusable, false otherwise.
Definition: EffectiveUrl.cc:67
void get_header(const std::string &name, std::string &value, bool &found)
get the value of the named header
void ingest_response_headers(const std::vector< std::string > &resp_hdrs)
Ingests the passed response hedaers.
virtual std::string dump()
Definition: url_impl.cc:335
virtual bool is_expired()
Definition: url_impl.cc:261
utility class for the HTTP catalog module
Definition: EffectiveUrl.cc:58