You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

160 lines
5.9 KiB

#include "WebResource.h"
#include <fstream>
#include <map>
#include <algorithm>
#include "networking/HTTPCommon.h"
#include "networking/HTTPRequest.h"
#include "networking/HTTPResponse.h"
#include "networking/HTTPSRequest.h"
#include "StringUtils.h"
#include <iostream>
#include "Log.h"
namespace {
// only used for local files atm
std::map<std::string, ResourceType> strToRT = {
{"html", ResourceType::HTML},
{"txt", ResourceType::TXT},
{"text", ResourceType::TXT},
{"css", ResourceType::CSS}, //TXT?
{"js", ResourceType::JS} //TXT?
};
bool isOnlineResource(URL const& url) {
return url.scheme != "file";
}
}
WebResource::WebResource() {
resourceType = ResourceType::INVALID;
raw = "";
}
WebResource::WebResource(ResourceType rtype, std::string const& rraw) {
resourceType = rtype;
raw = rraw;
}
WebResource getWebResource(URL const& url) {
if (isOnlineResource(url)) {
//std::cout << "WebReousrce::getWebResource - isOnline" << std::endl;
return getOnlineWebResource(url, nullptr);
}
//std::cout << "WebReousrce::getWebResource - isOffline" << std::endl;
return getLocalWebResource(url);
}
WebResource getLocalWebResource(URL const& url) {
std::string fileExtension = getFilenameExtension(url.path);
if (fileExtension.length() == 0) {
return WebResource(ResourceType::INVALID,
"Could not find any file extension");
}
// Convert file extension to lowercase for table lookup.
std::transform(fileExtension.begin(),
fileExtension.end(),
fileExtension.begin(),
tolower);
if (strToRT.find(fileExtension) == strToRT.end()) {
return WebResource(ResourceType::INVALID,
"Local file with extension " + fileExtension + " is not supported. Did you forget a http[s]://?");
}
std::ifstream in(url.path, std::ios::in | std::ios::binary);
if (in) {
// There exists more efficient ways of doing this, but it works for the
// time being.
std::string contents = std::string(std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>());
return WebResource(strToRT[fileExtension], contents);
}
return WebResource(ResourceType::INVALID,
"Could not open file " + url.path);
}
WebResource getOnlineWebResource(URL const& url, std::unique_ptr<std::map<std::string, std::string>> formData) {
std::shared_ptr<URL> uri=std::make_shared<URL>(url);
std::unique_ptr<std::string> ptrPostBody = nullptr;
if (formData) {
std::string postBody = "";
// iterator over formData
for (auto &entry : *formData) {
postBody += entry.first + "=" + entry.second + "&";
}
// strip last & off
postBody = postBody.substr(0, postBody.size() - 1);
std::cout << "postBody is " << postBody << std::endl;
// add to string
ptrPostBody = std::make_unique<std::string>(postBody);
}
WebResource returnRes;
std::string redirectLocation = "";
std::function<void(const HTTPResponse&)> responseCallback = [&](HTTPResponse const& response){
logDebug() << "getOnlineWebResource responseCallback got " << response.statusCode << std::endl;
if (response.statusCode == 301 || response.statusCode == 302 || response.statusCode == 303) {
std::string location;
if (response.properties.find("Location")==response.properties.end()) {
if (response.properties.find("location")==response.properties.end()) {
logDebug() << "getOnlineWebResource responseCallback - got " << response.statusCode << " without a location" << std::endl;
for(auto const &row : response.properties) {
logDebug() << "getOnlineWebResource responseCallback - " << row.first << "=" << response.properties.at(row.first) << std::endl;
}
redirectLocation = "_";
} else {
location = response.properties.at("location");
}
} else {
location = response.properties.at("Location");
}
logDebug() << "Redirect To: " << location << std::endl;
redirectLocation = location;
} else if (response.statusCode != 200) {
returnRes.resourceType = ResourceType::INVALID;
returnRes.raw = "Unsupported status code";
} else {
// TODO: Set resourceType based on Content-Type field.
std::string contentType = "";
if (response.properties.find("Content-type") != response.properties.end()) {
contentType = response.properties.at("Content-type");
}
if (response.properties.find("Content-Type") != response.properties.end()) {
contentType = response.properties.at("Content-Type");
}
std::cout << "Content-type: " << contentType << std::endl;
if (contentType == "text/plain") {
returnRes.resourceType = ResourceType::TXT;
} else if (contentType == "application/json") {
returnRes.resourceType = ResourceType::TXT;
} else {
returnRes.resourceType = ResourceType::HTML;
}
returnRes.raw = std::move(response.body);
}
};
if (uri->scheme == "https") {
HTTPSRequest secure(uri);
if (formData) {
secure.method = Method::POST;
}
//secure.version = Version::HTTP11;
secure.sendRequest(responseCallback, std::move(ptrPostBody));
} else {
HTTPRequest request(uri);
if (formData) {
request.method = Method::POST;
}
request.sendRequest(responseCallback, std::move(ptrPostBody));
}
return returnRes;
}