bes  Updated for version 3.20.13
HttpUtils.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 // This file is part of the BES http package, part of the Hyrax data server.
3 
4 // Copyright (c) 2020 OPeNDAP, Inc.
5 // Author: Nathan Potter <ndp@opendap.org>
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
22 
23 // Authors:
24 // ndp Nathan Potter <ndp@opendap.org>
25 
26 #include "config.h"
27 
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 
32 #include <cstdlib>
33 #include <cstring>
34 #include <string>
35 #include <map>
36 #include <vector>
37 #include <sstream>
38 #include <time.h>
39 
40 #include <curl/curl.h>
41 
42 #include "BESUtil.h"
43 #include "BESCatalogUtils.h"
44 #include "BESCatalogList.h"
45 #include "BESCatalog.h"
46 #include "BESRegex.h"
47 #include "TheBESKeys.h"
48 #include "BESInternalError.h"
49 #include "BESNotFoundError.h"
50 #include "BESSyntaxUserError.h"
51 #include "BESDebug.h"
52 #include "BESUtil.h"
53 
54 #include "HttpNames.h"
55 #include "HttpUtils.h"
56 #include "ProxyConfig.h"
57 
58 #define MODULE "http"
59 
60 using namespace std;
61 using namespace http;
62 
63 // These are static class members
64 
65 #define prolog string("HttpUtils::").append(__func__).append("() - ")
66 
67 namespace http {
72 void load_mime_list_from_keys(map<string, string> &mime_list)
73 {
74  // MimeTypes - translate from a mime type to a module name
75  bool found = false;
76  vector<string> vals;
77  TheBESKeys::TheKeys()->get_values(HTTP_MIMELIST_KEY, vals, found);
78  if (found && vals.size()) {
79  vector<string>::iterator i = vals.begin();
80  vector<string>::iterator e = vals.end();
81  for (; i != e; i++) {
82  size_t colon = (*i).find(":");
83  if (colon == string::npos) {
84  string err = (string) "Malformed " + HTTP_MIMELIST_KEY + " " + (*i) +
85  " specified in the gateway configuration";
86  throw BESSyntaxUserError(err, __FILE__, __LINE__);
87  }
88  string mod = (*i).substr(0, colon);
89  string mime = (*i).substr(colon + 1);
90  mime_list[mod] = mime;
91  }
92  }
93 }
94 
95 
96 
110 void get_type_from_disposition(const string &disp, string &type)
111 {
112  // If this function extracts a filename from disp and it matches a handler's
113  // regex using the Catalog Utils, this will be set to a non-empty value.
114  type = "";
115 
116  size_t fnpos = disp.find("filename");
117  if (fnpos != string::npos) {
118  // Got the filename attribute, now get the
119  // filename, which is after the pound sign (#)
120  size_t pos = disp.find("#", fnpos);
121  if (pos == string::npos) pos = disp.find("=", fnpos);
122  if (pos != string::npos) {
123  // Got the filename to the end of the
124  // string, now get it to either the end of
125  // the string or the start of the next
126  // attribute
127  string filename;
128  size_t sp = disp.find(" ", pos);
129  if (pos != string::npos) {
130  // space before the next attribute
131  filename = disp.substr(pos + 1, sp - pos - 1);
132  } else {
133  // to the end of the string
134  filename = disp.substr(pos + 1);
135  }
136 
138 
139  // we have the filename now, run it through
140  // the type match to get the file type.
141 
143  type = utils->get_handler_name(filename);
144  }
145  }
146 }
147 
148 void get_type_from_content_type(const string &ctype, string &type)
149 {
150  BESDEBUG(MODULE, prolog << "BEGIN content-type: " << ctype << endl);
151  map<string,string> mime_list;
152  load_mime_list_from_keys(mime_list);
153  map<string, string>::iterator i = mime_list.begin();
154  map<string, string>::iterator e = mime_list.end();
155  bool done = false;
156  for (; i != e && !done; i++) {
157  BESDEBUG(MODULE, prolog << "Comparing content type '" << ctype << "' against mime list element '" << (*i).second << "'" << endl);
158  BESDEBUG(MODULE, prolog << "first: " << (*i).first << " second: " << (*i).second << endl);
159  if ((*i).second == ctype) {
160  BESDEBUG(MODULE, prolog << "MATCH" << endl);
161  type = (*i).first;
162  done = true;
163  }
164  }
165  BESDEBUG(MODULE, prolog << "END" << endl);
166 }
167 
168 void get_type_from_url(const string &url, string &type) {
169  const BESCatalogUtils *utils = BESCatalogList::TheCatalogList()->find_catalog("catalog")->get_catalog_utils();
170 
171  type = utils->get_handler_name(url);
172 }
173 
179  size_t max_redirects=0;
180  bool found = false;
181  string value;
182  TheBESKeys::TheKeys()->get_value(HTTP_MAX_REDIRECTS_KEY, value, found);
183  if (found && !value.empty()) {
184  std::istringstream(value) >> max_redirects; // Returns 0 if the parse fails.
185  }
186  if(!max_redirects){
187  max_redirects = HTTP_MAX_REDIRECTS_DEFAULT;
188  }
189  return max_redirects;
190 }
191 
192 #if 0
209  void HttpUtils::decompose_url(const string target_url, map<string,string> &url_info)
210  {
211  string url_base;
212  string query_string;
213 
214  size_t query_index = target_url.find_first_of("?");
215  BESDEBUG(MODULE, prolog << "query_index: " << query_index << endl);
216  if(query_index != string::npos){
217  query_string = target_url.substr(query_index+1);
218  url_base = target_url.substr(0,query_index);
219  }
220  else {
221  url_base = target_url;
222  }
223  url_info.insert( std::pair<string,string>(HTTP_TARGET_URL_KEY,target_url));
224  BESDEBUG(MODULE, prolog << HTTP_TARGET_URL_KEY << ": " << target_url << endl);
225  url_info.insert( std::pair<string,string>(HTTP_URL_BASE_KEY,url_base));
226  BESDEBUG(MODULE, prolog << HTTP_URL_BASE_KEY <<": " << url_base << endl);
227  url_info.insert( std::pair<string,string>(HTTP_QUERY_STRING_KEY,query_string));
228  BESDEBUG(MODULE, prolog << HTTP_QUERY_STRING_KEY << ": " << query_string << endl);
229  if(!query_string.empty()){
230  vector<string> records;
231  string delimiters = "&";
232  BESUtil::tokenize(query_string,records, delimiters);
233  vector<string>::iterator i = records.begin();
234  for(; i!=records.end(); i++){
235  size_t index = i->find('=');
236  if(index != string::npos) {
237  string key = i->substr(0, index);
238  string value = i->substr(index+1);
239  BESDEBUG(MODULE, prolog << "key: " << key << " value: " << value << endl);
240  url_info.insert( std::pair<string,string>(key,value));
241  }
242  }
243  }
244  time_t now;
245  time(&now); /* get current time; same as: timer = time(NULL) */
246  stringstream unix_time;
247  unix_time << now;
248  url_info.insert( std::pair<string,string>(HTTP_INGEST_TIME_KEY,unix_time.str()));
249  }
250 
251 #endif
252 
253 }
254 
static BESCatalogList * TheCatalogList()
Get the singleton BESCatalogList instance.
virtual BESCatalog * default_catalog() const
The the default catalog.
std::string get_handler_name(const std::string &item) const
Find the handler name that will process.
virtual BESCatalogUtils * get_catalog_utils() const
Get a pointer to the utilities, customized for this catalog.
Definition: BESCatalog.h:112
error thrown if there is a user syntax error in the request or any other user error
static void tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters="/")
Definition: BESUtil.cc:992
static void trim_if_surrounding_quotes(std::string &value)
Remove double quotes around a string This function will remove a leading and/or trailing double quote...
Definition: BESUtil.cc:123
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:340
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:71
void get_values(const std::string &s, std::vector< std::string > &vals, bool &found)
Retrieve the values of a given key, if set.
Definition: TheBESKeys.cc:371
utility class for the HTTP catalog module
Definition: AllowedHosts.cc:55
size_t load_max_redirects_from_keys()
Definition: HttpUtils.cc:178
void get_type_from_disposition(const string &disp, string &type)
Definition: HttpUtils.cc:110
void load_mime_list_from_keys(map< string, string > &mime_list)
Definition: HttpUtils.cc:72