41#include "BESCatalogList.h"
47using std::chrono::system_clock;
49#define MODULE HTTP_MODULE
50#define prolog string("url::").append(__func__).append("() - ")
52#define PROTOCOL_KEY "http_url_protocol"
53#define HOST_KEY "http_url_host"
54#define PATH_KEY "http_url_path"
55#define QUERY_KEY "http_url_query"
56#define SOURCE_URL_KEY "http_url_target_url"
57#define INGEST_TIME_KEY "http_url_ingest_time"
67url::url(
const map<string,string> &kvp)
69 map<string,string> kvp_copy = kvp;
70 map<string,string>::const_iterator it;
71 map<string,string>::const_iterator itc;
73 it = kvp.find(PROTOCOL_KEY);
74 itc = kvp_copy.find(PROTOCOL_KEY);
75 if(it != kvp.end() && itc != kvp_copy.end()){
76 d_protocol = it->second;
77 kvp_copy.erase(it->first);
78 BESDEBUG(MODULE, prolog <<
"Located PROTOCOL_KEY(" << PROTOCOL_KEY <<
") value: " << d_protocol << endl);
80 it = kvp.find(HOST_KEY);
81 itc = kvp_copy.find(HOST_KEY);
82 if(it != kvp.end() && itc != kvp_copy.end()){
84 kvp_copy.erase(it->first);
85 BESDEBUG(MODULE, prolog <<
"Located HOST_KEY(" << HOST_KEY <<
") value: " << d_host << endl);
87 it = kvp.find(PATH_KEY);
88 itc = kvp_copy.find(PATH_KEY);
89 if(it != kvp.end() && itc != kvp_copy.end()){
91 kvp_copy.erase(it->first);
92 BESDEBUG(MODULE, prolog <<
"Located PATH_KEY(" << PATH_KEY <<
") value: " << d_path << endl);
94 it = kvp.find(QUERY_KEY);
95 itc = kvp_copy.find(QUERY_KEY);
96 if(it != kvp.end() && itc != kvp_copy.end()){
98 kvp_copy.erase(it->first);
99 BESDEBUG(MODULE, prolog <<
"Located QUERY_KEY(" << QUERY_KEY <<
") value: " << d_query << endl);
101 it = kvp.find(SOURCE_URL_KEY);
102 itc = kvp_copy.find(SOURCE_URL_KEY);
103 if(it != kvp.end() && itc != kvp_copy.end()){
104 d_source_url_str = it->second;
105 kvp_copy.erase(it->first);
106 BESDEBUG(MODULE, prolog <<
"Located SOURCE_URL_KEY(" << SOURCE_URL_KEY <<
") value: " << d_source_url_str << endl);
109 for(itc = kvp_copy.begin(); itc != kvp_copy.end(); itc++){
110 string key = itc->first;
111 string value = itc->second;
112 map<string, vector<string>* >::const_iterator record_it;
113 record_it = d_query_kvp.find(key);
114 if(record_it != d_query_kvp.end()){
115 vector<string> *values = record_it->second;
116 values->push_back(value);
119 vector<string> *values =
new vector<string>();
120 values->push_back(value);
121 d_query_kvp.insert(pair<
string, vector<string>*>(key, values));
133 if(!d_query_kvp.empty()){
134 map<string, vector<string>* >::const_iterator it;
135 for(it = d_query_kvp.begin() ; it != d_query_kvp.end(); it++){
149 const string protocol_end(
"://");
150 BESDEBUG(MODULE, prolog <<
"BEGIN (parsing: '" << d_source_url_str <<
"')" << endl);
156 if(d_source_url_str.find(protocol_end) == string::npos){
161 BESDEBUG(MODULE, prolog <<
"Searching for catalog: " << default_catalog_name << endl);
162 BESCatalog *bcat = bcl->find_catalog(default_catalog_name);
164 BESDEBUG(MODULE, prolog <<
"Found catalog: " << bcat->
get_catalog_name() << endl);
166 string msg =
"OUCH! Unable to locate default catalog!";
167 BESDEBUG(MODULE, prolog << msg << endl);
170 string catalog_root = bcat->
get_root();
171 BESDEBUG(MODULE, prolog <<
"Catalog root: " << catalog_root << endl);
174 if(file_path[0] !=
'/')
175 file_path =
"/" + file_path;
176 d_source_url_str = FILE_PROTOCOL + file_path;
179 const string parse_url_target(d_source_url_str);
181 string::const_iterator prot_i = search(parse_url_target.begin(), parse_url_target.end(),
182 protocol_end.begin(), protocol_end.end());
184 if (prot_i != parse_url_target.end())
185 advance(prot_i, protocol_end.length());
187 d_protocol.reserve(distance(parse_url_target.begin(), prot_i));
188 transform(parse_url_target.begin(), prot_i,
189 back_inserter(d_protocol),
190 [](
int c) {
return tolower(c); });
191 if (prot_i == parse_url_target.end())
194 if (d_protocol == FILE_PROTOCOL) {
195 d_path = parse_url_target.substr(d_protocol.length());
196 BESDEBUG(MODULE, prolog <<
"FILE_PROTOCOL d_path: " << d_path << endl);
198 else if( d_protocol == HTTP_PROTOCOL || d_protocol == HTTPS_PROTOCOL){
199 string::const_iterator path_i = find(prot_i, parse_url_target.end(),
'/');
200 d_host.reserve(distance(prot_i, path_i));
201 transform(prot_i, path_i,
202 back_inserter(d_host),
203 [](
int c) {
return tolower(c); });
204 string::const_iterator query_i = find(path_i, parse_url_target.end(),
'?');
205 d_path.assign(path_i, query_i);
206 if (query_i != parse_url_target.end())
208 d_query.assign(query_i, parse_url_target.end());
210 if (!d_query.empty()) {
211 vector<string> records;
212 string delimiters =
"&";
214 vector<string>::iterator i = records.begin();
215 for (; i != records.end(); i++) {
216 size_t index = i->find(
'=');
217 if (index != string::npos) {
218 string key = i->substr(0, index);
219 string value = i->substr(index + 1);
220 BESDEBUG(MODULE, prolog <<
"key: " << key <<
" value: " << value << endl);
221 map<string, vector<string> *>::const_iterator record_it;
222 record_it = d_query_kvp.find(key);
223 if (record_it != d_query_kvp.end()) {
224 vector<string> *values = record_it->second;
225 values->push_back(value);
227 vector<string> *values =
new vector<string>();
228 values->push_back(value);
229 d_query_kvp.insert(pair<
string, vector<string> *>(key, values));
237 msg << prolog <<
"Unsupported URL protocol " << d_protocol <<
" found in URL: " << d_source_url_str;
238 BESDEBUG(MODULE, msg.str() << endl);
241 BESDEBUG(MODULE, prolog <<
"END (parsing: '" << d_source_url_str <<
"')" << endl);
254 map<string, vector<string>* >::const_iterator it;
255 it = d_query_kvp.find(key);
256 if(it != d_query_kvp.end()){
257 vector<string> *values = it->second;
258 if(!values->empty()){
259 value = (*values)[0];
272 map<string, vector<string>* >::const_iterator it;
273 it = d_query_kvp.find(key);
274 if(it != d_query_kvp.end()){
275 values = *it->second;
285void url::kvp(map<string,string> &kvp){
289 kvp.insert(pair<string,string>(PROTOCOL_KEY, d_protocol));
290 kvp.insert(pair<string,string>(HOST_KEY, d_host));
291 kvp.insert(pair<string,string>(PATH_KEY, d_path));
292 kvp.insert(pair<string,string>(QUERY_KEY, d_query));
293 kvp.insert(pair<string,string>(SOURCE_URL_KEY, d_source_url_str));
295 kvp.insert(pair<string,string>(INGEST_TIME_KEY,ss.str()));
298 map<string, vector<string>* >::const_iterator it;
299 for(it=d_query_kvp.begin(); it != d_query_kvp.end(); it++){
300 kvp.insert(pair<string,string>(it->first,(*it->second)[0]));
315 std::time_t now = system_clock::to_time_t(system_clock::now());
317 BESDEBUG(MODULE, prolog <<
"now: " << now << endl);
319 std::time_t expires_time = ingest_time() + HTTP_EFFECTIVE_URL_DEFAULT_EXPIRES_INTERVAL;
324 if(!cf_expires.empty()){
325 std::istringstream(cf_expires) >> expires_time;
326 BESDEBUG(MODULE, prolog <<
"Using "<< CLOUDFRONT_EXPIRES_HEADER_KEY <<
": " << expires_time << endl);
328 else if(!aws_expires_str.empty()){
330 long long aws_expires;
331 std::istringstream(aws_expires_str) >> aws_expires;
335 std::time_t aws_start_time = ingest_time();
341 if(!aws_date.empty()){
343 string date = aws_date;
344 string year = date.substr(0,4);
345 string month = date.substr(4,2);
346 string day = date.substr(6,2);
347 string hour = date.substr(9,2);
348 string minute = date.substr(11,2);
349 string second = date.substr(13,2);
351 BESDEBUG(MODULE, prolog <<
"date: "<< date <<
352 " year: " << year <<
" month: " << month <<
" day: " << day <<
353 " hour: " << hour <<
" minute: " << minute <<
" second: " << second << endl);
357 BESDEBUG(MODULE, prolog <<
"old_now: " << old_now << endl);
358 struct tm *ti = gmtime(&old_now);
359 ti->tm_year = stoll(year) - 1900;
360 ti->tm_mon = stoll(month) - 1;
361 ti->tm_mday = stoll(day);
362 ti->tm_hour = stoll(hour);
363 ti->tm_min = stoll(minute);
364 ti->tm_sec = stoll(second);
366 BESDEBUG(MODULE, prolog <<
"ti->tm_year: "<< ti->tm_year <<
367 " ti->tm_mon: " << ti->tm_mon <<
368 " ti->tm_mday: " << ti->tm_mday <<
369 " ti->tm_hour: " << ti->tm_hour <<
370 " ti->tm_min: " << ti->tm_min <<
371 " ti->tm_sec: " << ti->tm_sec << endl);
374 aws_start_time = mktime(ti);
375 BESDEBUG(MODULE, prolog <<
"AWS start_time (computed): " << aws_start_time << endl);
378 expires_time = aws_start_time + aws_expires;
379 BESDEBUG(MODULE, prolog <<
"Using "<< AMS_EXPIRES_HEADER_KEY <<
": " << aws_expires <<
380 " (expires_time: " << expires_time <<
")" << endl);
382 std::time_t remaining = expires_time - now;
383 BESDEBUG(MODULE, prolog <<
"expires_time: " << expires_time <<
384 " remaining: " << remaining <<
385 " threshold: " << HTTP_URL_REFRESH_THRESHOLD << endl);
387 stale = remaining < HTTP_URL_REFRESH_THRESHOLD;
388 BESDEBUG(MODULE, prolog <<
"stale: " << (stale?
"true":
"false") << endl);
399 string indent_inc =
" ";
400 string indent = indent_inc;
402 ss <<
"http::url [" <<
this <<
"] " << endl;
403 ss << indent <<
"d_source_url_str: " << d_source_url_str << endl;
404 ss << indent <<
"d_protocol: " << d_protocol << endl;
405 ss << indent <<
"d_host: " << d_host << endl;
406 ss << indent <<
"d_path: " << d_path << endl;
407 ss << indent <<
"d_query: " << d_query << endl;
409 std::map<std::string, std::vector<std::string>* >::iterator it;
411 string idt = indent+indent_inc;
412 for(it=d_query_kvp.begin(); it !=d_query_kvp.end(); it++){
413 ss << indent <<
"d_query_kvp["<<it->first<<
"]: " << endl;
414 std::vector<std::string> *values = it->second;
415 for(
size_t i=0; i<values->size(); i++){
416 ss << idt <<
"value[" << i <<
"]: " << (*values)[i] << endl;
419 ss << indent <<
"d_ingest_time: " << d_ingest_time.time_since_epoch().count() << endl;
List of all registered catalogs.
virtual std::string default_catalog_name() const
The name of the default catalog.
static BESCatalogList * TheCatalogList()
Get the singleton BESCatalogList instance.
Catalogs provide a hierarchical organization for data.
virtual std::string get_root() const =0
virtual std::string get_catalog_name() const
Get the name for this catalog.
exception thrown if internal error encountered
static void tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters="/")
static std::string pathConcat(const std::string &firstPart, const std::string &secondPart, char separator='/')
Concatenate path fragments making sure that they are separated by a single '/' character.
virtual void query_parameter_values(const std::string &key, std::vector< std::string > &values) const
virtual std::string query_parameter_value(const std::string &key) const
virtual std::string dump()
virtual bool is_expired()
utility class for the HTTP catalog module