Permalink
Browse files

Upgrade to 0.1.5

  • Loading branch information...
1 parent 854d44e commit c65a57e888ee48eaa948e590c90c51420bffa847 @cmouse cmouse committed Jan 19, 2015
Showing with 85 additions and 46 deletions.
  1. +70 −44 pdns/ext/yahttp/yahttp/reqresp.cpp
  2. +15 −2 pdns/ext/yahttp/yahttp/reqresp.hpp
@@ -20,8 +20,16 @@ namespace YaHTTP {
std::string tmpurl;
std::istringstream iss(line);
iss >> target->method >> tmpurl >> ver;
- if (ver.find("HTTP/1.") != 0)
- throw ParseError("Not a HTTP 1.x request");
+ if (ver.size() == 0)
+ target->version = 9;
+ else if (ver.find("HTTP/0.9") == 0)
+ target->version = 9;
+ else if (ver.find("HTTP/1.0") == 0)
+ target->version = 10;
+ else if (ver.find("HTTP/1.1") == 0)
+ target->version = 11;
+ else
+ throw ParseError("HTTP version not supported");
// uppercase the target method
std::transform(target->method.begin(), target->method.end(), target->method.begin(), ::toupper);
target->url.parse(tmpurl);
@@ -30,9 +38,25 @@ namespace YaHTTP {
} else if(target->kind == YAHTTP_TYPE_RESPONSE) {
std::string ver;
std::istringstream iss(line);
- iss >> ver >> target->status >> target->statusText;
- if (ver.find("HTTP/1.") != 0)
- throw ParseError("Not a HTTP 1.x response");
+ std::string::size_type pos1;
+ iss >> ver >> target->status;
+ std::getline(iss, target->statusText);
+ pos1=0;
+ while(pos1 < target->statusText.size() && ::isspace(target->statusText.at(pos1))) pos1++;
+ target->statusText = target->statusText.substr(pos1);
+ if ((pos1 = target->statusText.find("\r")) != std::string::npos) {
+ target->statusText = target->statusText.substr(0, pos1-1);
+ }
+ if (ver.size() == 0) {
+ target->version = 9;
+ } else if (ver.find("HTTP/0.9") == 0)
+ target->version = 9;
+ else if (ver.find("HTTP/1.0") == 0)
+ target->version = 10;
+ else if (ver.find("HTTP/1.1") == 0)
+ target->version = 11;
+ else
+ throw ParseError("HTTP version not supported");
state = 1;
}
} else if (state == 1) {
@@ -49,9 +73,9 @@ namespace YaHTTP {
key = line.substr(0, pos);
value = line.substr(pos+2);
for(std::string::iterator it=key.begin(); it != key.end(); it++)
- if (std::isspace(*it))
+ if (std::isspace(*it))
throw ParseError("Header key contains whitespace which is not allowed by RFC");
-
+
Utility::trim(value);
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
// is it already defined
@@ -61,7 +85,7 @@ namespace YaHTTP {
target->jar.parseCookieHeader(value);
} else {
if (key == "host" && target->kind == YAHTTP_TYPE_REQUEST) {
- // maybe it contains port?
+ // maybe it contains port?
if ((pos = value.find(":")) == std::string::npos) {
target->url.host = value;
} else {
@@ -81,9 +105,9 @@ namespace YaHTTP {
minbody = 0;
// check for expected body size
if (target->kind == YAHTTP_TYPE_REQUEST) maxbody = target->max_request_size;
- else if (target->kind == YAHTTP_TYPE_RESPONSE) maxbody = target->max_response_size;
+ else if (target->kind == YAHTTP_TYPE_RESPONSE) maxbody = target->max_response_size;
else maxbody = 0;
-
+
if (!chunked) {
if (target->headers.find("content-length") != target->headers.end()) {
std::istringstream maxbodyS(target->headers["content-length"]);
@@ -119,17 +143,17 @@ namespace YaHTTP {
if (buffer.at(chunk_size) == '\r') {
if (buffer.size() < static_cast<size_t>(chunk_size+2) || buffer.at(chunk_size+1) != '\n') return false; // expect newline after carriage return
crlf=2;
- } else if (buffer.at(chunk_size) != '\n') return false;
+ } else if (buffer.at(chunk_size) != '\n') return false;
std::string tmp = buffer.substr(0, chunk_size);
buffer.erase(buffer.begin(), buffer.begin()+chunk_size+crlf);
bodybuf << tmp;
chunk_size = 0;
if (buffer.size() == 0) break; // just in case
}
} else {
- if (bodybuf.str().length() + buffer.length() > maxbody)
+ if (bodybuf.str().length() + buffer.length() > maxbody)
bodybuf << buffer.substr(0, maxbody - bodybuf.str().length());
- else
+ else
bodybuf << buffer;
buffer = "";
}
@@ -139,50 +163,52 @@ namespace YaHTTP {
return ready();
};
-
+
void HTTPBase::write(std::ostream& os) const {
if (kind == YAHTTP_TYPE_REQUEST) {
std::ostringstream getparmbuf;
std::string getparms;
- // prepare URL
+ // prepare URL
for(strstr_map_t::const_iterator i = getvars.begin(); i != getvars.end(); i++) {
getparmbuf << Utility::encodeURL(i->first, false) << "=" << Utility::encodeURL(i->second, false) << "&";
}
- if (getparmbuf.str().length() > 0)
+ if (getparmbuf.str().length() > 0)
getparms = "?" + std::string(getparmbuf.str().begin(), getparmbuf.str().end() - 1);
else
getparms = "";
- os << method << " " << url.path << getparms << " HTTP/1.1";
+ os << method << " " << url.path << getparms << " HTTP/" << versionStr(this->version);
} else if (kind == YAHTTP_TYPE_RESPONSE) {
- os << "HTTP/1.1 " << status << " ";
+ os << "HTTP/" << versionStr(this->version) << " " << status << " ";
if (statusText.empty())
os << Utility::status2text(status);
else
os << statusText;
}
os << "\r\n";
-
+
bool cookieSent = false;
bool sendChunked = false;
-
- if (headers.find("content-length") == headers.end()) {
- // must use chunked on response
- sendChunked = (kind == YAHTTP_TYPE_RESPONSE);
- if ((headers.find("transfer-encoding") != headers.end() && headers.find("transfer-encoding")->second != "chunked")) {
- throw YaHTTP::Error("Transfer-encoding must be chunked, or Content-Length defined");
- }
- if ((headers.find("transfer-encoding") == headers.end() && kind == YAHTTP_TYPE_RESPONSE)) {
- sendChunked = true;
- // write the header now
- os << "Transfer-Encoding: chunked" << "\r\n";
- }
- } else {
- if ((headers.find("transfer-encoding") == headers.end() && kind == YAHTTP_TYPE_RESPONSE)) {
- sendChunked = true;
- // write the header now
- os << "Transfer-Encoding: chunked" << "\r\n";
- } else if (headers.find("transfer-encoding") != headers.end() && headers.find("transfer-encoding")->second == "chunked") {
- sendChunked = true;
+
+ if (this->version > 10) { // 1.1 or better
+ if (headers.find("content-length") == headers.end()) {
+ // must use chunked on response
+ sendChunked = (kind == YAHTTP_TYPE_RESPONSE);
+ if ((headers.find("transfer-encoding") != headers.end() && headers.find("transfer-encoding")->second != "chunked")) {
+ throw YaHTTP::Error("Transfer-encoding must be chunked, or Content-Length defined");
+ }
+ if ((headers.find("transfer-encoding") == headers.end() && kind == YAHTTP_TYPE_RESPONSE)) {
+ sendChunked = true;
+ // write the header now
+ os << "Transfer-Encoding: chunked" << "\r\n";
+ }
+ } else {
+ if ((headers.find("transfer-encoding") == headers.end() && kind == YAHTTP_TYPE_RESPONSE)) {
+ sendChunked = true;
+ // write the header now
+ os << "Transfer-Encoding: chunked" << "\r\n";
+ } else if (headers.find("transfer-encoding") != headers.end() && headers.find("transfer-encoding")->second == "chunked") {
+ sendChunked = true;
+ }
}
}
@@ -209,16 +235,16 @@ namespace YaHTTP {
#ifdef HAVE_CPP_FUNC_PTR
this->renderer(this, os, sendChunked);
#else
- SendbodyRenderer r;
+ SendbodyRenderer r;
r(this, os, chunked)
#endif
};
-
+
std::ostream& operator<<(std::ostream& os, const Response &resp) {
resp.write(os);
return os;
};
-
+
std::istream& operator>>(std::istream& is, Response &resp) {
YaHTTP::AsyncResponseLoader arl;
arl.initialize(&resp);
@@ -231,17 +257,17 @@ namespace YaHTTP {
}
}
// throw unless ready
- if (arl.ready() == false)
+ if (arl.ready() == false)
throw ParseError("Was not able to extract a valid Response from stream");
arl.finalize();
return is;
};
-
+
std::ostream& operator<<(std::ostream& os, const Request &req) {
req.write(os);
return os;
};
-
+
std::istream& operator>>(std::istream& is, Request &req) {
YaHTTP::AsyncRequestLoader arl;
arl.initialize(&req);
@@ -78,6 +78,8 @@ namespace YaHTTP {
std::ifstream ifs(path.c_str(), std::ifstream::binary);
#endif
n = 0;
+
+ std::cerr << "Sending file " << path << std::endl;
while(ifs && ifs.good()) {
ifs.read(buf, sizeof buf);
n += (k = ifs.gcount());
@@ -116,6 +118,7 @@ namespace YaHTTP {
postvars.clear();
body = "";
routeName = "";
+ version = 11; // default to version 1.1
}
protected:
HTTPBase(const HTTPBase& rhs) {
@@ -125,7 +128,7 @@ namespace YaHTTP {
this->jar = rhs.jar; this->postvars = rhs.postvars;
this->parameters = rhs.parameters; this->getvars = rhs.getvars;
this->body = rhs.body; this->max_request_size = rhs.max_request_size;
- this->max_response_size = rhs.max_response_size;
+ this->max_response_size = rhs.max_response_size; this->version = rhs.version;
#ifdef HAVE_CPP_FUNC_PTR
this->renderer = rhs.renderer;
#endif
@@ -137,7 +140,7 @@ namespace YaHTTP {
this->jar = rhs.jar; this->postvars = rhs.postvars;
this->parameters = rhs.parameters; this->getvars = rhs.getvars;
this->body = rhs.body; this->max_request_size = rhs.max_request_size;
- this->max_response_size = rhs.max_response_size;
+ this->max_response_size = rhs.max_response_size; this->version = rhs.version;
#ifdef HAVE_CPP_FUNC_PTR
this->renderer = rhs.renderer;
#endif
@@ -147,6 +150,7 @@ namespace YaHTTP {
URL url; //<! URL of this request/response
int kind; //<! Type of object (1 = request, 2 = response)
int status; //<! status code
+ int version; //<! http version 9 = 0.9, 10 = 1.0, 11 = 1.1
std::string statusText; //<! textual representation of status code
std::string method; //<! http verb
strstr_map_t headers; //<! map of header(s)
@@ -171,6 +175,15 @@ namespace YaHTTP {
strstr_map_t& POST() { return postvars; }; //<! accessor for postvars
strcookie_map_t& COOKIES() { return jar.cookies; }; //<! accessor for cookies
+ std::string versionStr(int version) const {
+ switch(version) {
+ case 9: return "0.9";
+ case 10: return "1.0";
+ case 11: return "1.1";
+ default: throw YaHTTP::Error("Unsupported version");
+ }
+ };
+
std::string str() const {
std::ostringstream oss;
write(oss);

0 comments on commit c65a57e

Please sign in to comment.