extended request and get to optionally retrieve last-modified header, fix for potentially wrong content-length extraction
This commit is contained in:
@@ -110,15 +110,22 @@ void HttpClient::disconnect() {
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpClient::get(const string& uri, const string& body, string& response) {
|
||||
return request("GET", uri, body, response);
|
||||
bool HttpClient::get(const string& uri, const string& body, string& response, time_t* time) {
|
||||
return request("GET", uri, body, response, time);
|
||||
}
|
||||
|
||||
bool HttpClient::post(const string& uri, const string& body, string& response) {
|
||||
return request("POST", uri, body, response);
|
||||
}
|
||||
|
||||
bool HttpClient::request(const string& method, const string& uri, const string& body, string& response) {
|
||||
const int indexToMonth[] = {
|
||||
-1, -1, 2, 12, -1, -1, 1, -1, // 0-7
|
||||
-1, -1, -1, -1, 7, -1, 6, 8, // 8-15
|
||||
9, 5, 3, -1, 10, -1, 11, -1, // 16-23
|
||||
-1, -1, 4, -1, -1, -1, -1, -1, // 24-31
|
||||
};
|
||||
|
||||
bool HttpClient::request(const string& method, const string& uri, const string& body, string& response, time_t* time) {
|
||||
if (!ensureConnected()) {
|
||||
response = "not connected";
|
||||
return false;
|
||||
@@ -169,14 +176,54 @@ bool HttpClient::request(const string& method, const string& uri, const string&
|
||||
return false;
|
||||
}
|
||||
string headers = result.substr(0, pos+2); // including final \r\n
|
||||
const char* hdrs = headers.c_str();
|
||||
response = result.substr(pos+4);
|
||||
pos = headers.find("Content-Length: "); // 16 chars
|
||||
if (time) {
|
||||
pos = headers.find("\r\nLast-Modified: ");
|
||||
if (pos != string::npos && headers.substr(pos+42, 4) == " GMT") {
|
||||
// Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
|
||||
struct tm t;
|
||||
pos += strlen("\r\nLast-Modified: ") + 5;
|
||||
char* strEnd = NULL;
|
||||
t.tm_mday = (int)strtol(hdrs + pos, &strEnd, 10);
|
||||
if (strEnd != hdrs + pos + 2 || t.tm_mday < 1 || t.tm_mday > 31) {
|
||||
t.tm_mday = -1;
|
||||
}
|
||||
t.tm_mon = indexToMonth[((hdrs[pos+4]&0x10)>>1) | (hdrs[pos+5]&0x17)] - 1;
|
||||
strEnd = NULL;
|
||||
t.tm_year = (int)strtol(hdrs + pos + 7, &strEnd, 10);
|
||||
if (strEnd != hdrs + pos + 11 || t.tm_year < 1970 || t.tm_year >= 3000) {
|
||||
t.tm_year = -1;
|
||||
} else {
|
||||
t.tm_year -= 1900;
|
||||
}
|
||||
strEnd = NULL;
|
||||
t.tm_hour = (int)strtol(hdrs + pos + 12, &strEnd, 10);
|
||||
if (strEnd != hdrs + pos + 14 || t.tm_hour > 23) {
|
||||
t.tm_hour = -1;
|
||||
}
|
||||
strEnd = NULL;
|
||||
t.tm_min = (int)strtol(hdrs + pos + 15, &strEnd, 10);
|
||||
if (strEnd != hdrs + pos + 17 || t.tm_min > 59) {
|
||||
t.tm_min = -1;
|
||||
}
|
||||
strEnd = NULL;
|
||||
t.tm_sec = (int)strtol(hdrs + pos + 18, &strEnd, 10);
|
||||
if (strEnd != hdrs + pos + 20 || t.tm_sec > 59) {
|
||||
t.tm_sec = -1;
|
||||
}
|
||||
if (t.tm_mday > 0 && t.tm_mon >= 0 && t.tm_year >= 0 && t.tm_hour >= 0 && t.tm_min >=0 && t.tm_sec >= 0) {
|
||||
*time = timegm(&t);
|
||||
}
|
||||
};
|
||||
}
|
||||
pos = headers.find("\r\nContent-Length: "); // 16 chars
|
||||
if (pos == string::npos) {
|
||||
disconnect();
|
||||
return true;
|
||||
}
|
||||
char* strEnd = NULL;
|
||||
unsigned long length = strtoul(headers.c_str()+pos+16, &strEnd, 10);
|
||||
unsigned long length = strtoul(hdrs+pos+strlen("\r\nContent-Length: "), &strEnd, 10);
|
||||
if (strEnd == NULL || *strEnd != '\r') {
|
||||
disconnect();
|
||||
response = "invalid content length ";
|
||||
|
||||
@@ -100,9 +100,10 @@ class HttpClient {
|
||||
* @param uri the URI string.
|
||||
* @param body the optional body to send.
|
||||
* @param response the response body from the server (or the HTTP header on error).
|
||||
* @param time optional pointer to a @a time_t value for storing the modification time of the file, or NULL.
|
||||
* @return true on success, false on error.
|
||||
*/
|
||||
bool get(const string& uri, const string& body, string& response);
|
||||
bool get(const string& uri, const string& body, string& response, time_t* time = NULL);
|
||||
|
||||
/**
|
||||
* Execute a POST request.
|
||||
@@ -118,9 +119,10 @@ class HttpClient {
|
||||
* @param uri the URI string.
|
||||
* @param body the optional body to send.
|
||||
* @param response the response body from the server (or the HTTP header on error).
|
||||
* @param time optional pointer to a @a time_t value for storing the modification time of the file, or NULL.
|
||||
* @return true on success, false on error.
|
||||
*/
|
||||
bool request(const string& method, const string& uri, const string& body, string& response);
|
||||
bool request(const string& method, const string& uri, const string& body, string& response, time_t* time = NULL);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user