http: Support redirects for load URL too.

Might as well, especially to keep old recent entries working.
This commit is contained in:
Unknown W. Brackets committed 2019-06-23 13:12:13 -07:00
1 parent c5e2c0e6cd
commit 94e6950d48
4 files changed
+110 -49

No files matched your search

+79 -36
View File
@@ -27,43 +27,53 @@ HTTPFileLoader::HTTPFileLoader(const std::string &filename)
void HTTPFileLoader::Prepare() {
std::call_once(preparedFlag_, [this](){
if (!url_.Valid()) {
ERROR_LOG(LOADER, "HTTP request failed, invalid URL");
latestError_ = "Invalid URL";
return;
}
if (!client_.Resolve(url_.Host().c_str(), url_.Port())) {
ERROR_LOG(LOADER, "HTTP request failed, unable to resolve: %s port %d", url_.Host().c_str(), url_.Port());
latestError_ = "Could not connect (name not resolved)";
return;
}
client_.SetDataTimeout(20.0);
Connect();
if (!connected_) {
ERROR_LOG(LOADER, "HTTP request failed, failed to connect: %s port %d", url_.Host().c_str(), url_.Port());
latestError_ = "Could not connect (refused to connect)";
return;
}
int err = client_.SendRequest("HEAD", url_.Resource().c_str());
if (err < 0) {
ERROR_LOG(LOADER, "HTTP request failed, failed to send request: %s port %d", url_.Host().c_str(), url_.Port());
latestError_ = "Could not connect (could not request data)";
Disconnect();
return;
}
Buffer readbuf;
std::vector<std::string> responseHeaders;
int code = client_.ReadResponseHeaders(&readbuf, responseHeaders);
if (code != 200) {
// Leave size at 0, invalid.
ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename_.c_str());
latestError_ = "Could not connect (invalid response)";
Disconnect();
return;
Url resourceURL = url_;
int redirectsLeft = 20;
while (redirectsLeft > 0) {
responseHeaders.clear();
int code = SendHEAD(resourceURL, responseHeaders);
if (code == -400) {
// Already reported the error.
return;
}
if (code == 301 || code == 302 || code == 303 || code == 307 || code == 308) {
Disconnect();
std::string redirectURL;
if (http::GetHeaderValue(responseHeaders, "Location", &redirectURL)) {
Url url(resourceURL);
url = url.Relative(redirectURL);
if (url.ToString() == url_.ToString() || url.ToString() == resourceURL.ToString()) {
ERROR_LOG(LOADER, "HTTP request failed, hit a redirect loop");
latestError_ = "Could not connect (redirect loop)";
return;
}
resourceURL = url;
redirectsLeft--;
continue;
}
// No Location header?
ERROR_LOG(LOADER, "HTTP request failed, invalid redirect");
latestError_ = "Could not connect (invalid response)";
return;
}
if (code != 200) {
// Leave size at 0, invalid.
ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename_.c_str());
latestError_ = "Could not connect (invalid response)";
Disconnect();
return;
}
// We got a good, non-redirect response.
redirectsLeft = 0;
url_ = resourceURL;
}
// TODO: Expire cache via ETag, etc.
@@ -102,6 +112,39 @@ void HTTPFileLoader::Prepare() {
});
}
int HTTPFileLoader::SendHEAD(const Url &url, std::vector<std::string> &responseHeaders) {
if (!url.Valid()) {
ERROR_LOG(LOADER, "HTTP request failed, invalid URL");
latestError_ = "Invalid URL";
return -400;
}
if (!client_.Resolve(url.Host().c_str(), url.Port())) {
ERROR_LOG(LOADER, "HTTP request failed, unable to resolve: |%s| port %d", url.Host().c_str(), url.Port());
latestError_ = "Could not connect (name not resolved)";
return -400;
}
client_.SetDataTimeout(20.0);
Connect();
if (!connected_) {
ERROR_LOG(LOADER, "HTTP request failed, failed to connect: %s port %d", url.Host().c_str(), url.Port());
latestError_ = "Could not connect (refused to connect)";
return -400;
}
int err = client_.SendRequest("HEAD", url.Resource().c_str());
if (err < 0) {
ERROR_LOG(LOADER, "HTTP request failed, failed to send request: %s port %d", url.Host().c_str(), url.Port());
latestError_ = "Could not connect (could not request data)";
Disconnect();
return -400;
}
Buffer readbuf;
return client_.ReadResponseHeaders(&readbuf, responseHeaders);
}
HTTPFileLoader::~HTTPFileLoader() {
Disconnect();
}