summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2011-11-15 20:58:40 -0800
committerPixel <pixel@nobis-crew.org>2011-11-15 20:58:40 -0800
commit1d2fae393284de059619c21dcc84fcb9f1dc5e91 (patch)
treedd17d1e3794102cb343229955fadbb8e7f1e770d
parente2f4752ab5f0e6dba96df8d7c35e102ded57c3f9 (diff)
A bit more work on the HTTP server. Only the parsing of the POST method is remaining. Multipart is going to be cumbersome.
-rw-r--r--src/HttpServer.cc116
1 files changed, 101 insertions, 15 deletions
diff --git a/src/HttpServer.cc b/src/HttpServer.cc
index 3191bc1..f903093 100644
--- a/src/HttpServer.cc
+++ b/src/HttpServer.cc
@@ -19,8 +19,9 @@ class HttpWorker : public Task {
bool handleClient();
void send400(Events::BaseEvent * evt);
+ String httpUnescape(const char * in);
- IO<Socket> m_socket;
+ IO<Handle> m_socket;
IO<BStream> m_strm;
String m_name;
@@ -42,6 +43,37 @@ Balau::HttpWorker::~HttpWorker() {
}
}
+Balau::String Balau::HttpWorker::httpUnescape(const char * in) {
+ String r;
+ const char * p;
+ char hexa[3];
+ char out;
+
+ for (p = in; *p; p++) {
+ switch (*p) {
+ case '+':
+ r += String(" ", 1);
+ break;
+ case '%':
+ hexa[0] = *++p;
+ if (!hexa[0])
+ return r;
+ hexa[1] = *++p;
+ if (!hexa[1])
+ return r;
+ hexa[2] = 0;
+ out = strtol(hexa, NULL, 16);
+ r += String(&out, 1);
+ break;
+ default:
+ r += String(p, 1);
+ break;
+ }
+ }
+
+ return r;
+}
+
void Balau::HttpWorker::send400(Events::BaseEvent * evt) {
static const char str[] =
"HTTP/1.0 400 Bad Request\r\n"
@@ -70,13 +102,16 @@ bool Balau::HttpWorker::handleClient() {
waitFor(&evtTimeout);
setOkayToEAgain(true);
+ typedef std::map<String, String> StringMap;
+
String line;
bool gotFirst = false;
int method = -1;
- String url;
- String HttpVersion;
- typedef std::map<String, String> HttpHeaders_t;
- HttpHeaders_t HttpHeaders;
+ String host;
+ String uri;
+ String httpVersion;
+ StringMap httpHeaders;
+ StringMap variables;
if (m_postData) {
free(m_postData);
m_postData = NULL;
@@ -104,7 +139,7 @@ bool Balau::HttpWorker::handleClient() {
gotFirst = true;
int urlBegin = 0;
- // first line is in the form of METHOD URL HTTP/1.x
+ // first line is in the form of METHOD URL HTTP/xxx
switch(line[0]) {
case 'G':
if ((line[1] == 'E') && (line[2] == 'T') && (line[3] == ' ')) {
@@ -131,7 +166,7 @@ bool Balau::HttpWorker::handleClient() {
return false;
}
- url = line.extract(urlBegin, urlEnd - urlBegin + 1);
+ uri = line.extract(urlBegin, urlEnd - urlBegin + 1);
int httpBegin = urlEnd + 2;
@@ -145,13 +180,13 @@ bool Balau::HttpWorker::handleClient() {
(line[httpBegin + 2] == 'T') &&
(line[httpBegin + 3] == 'P') &&
(line[httpBegin + 4] == '/')) {
- HttpVersion = line.extract(httpBegin + 5);
+ httpVersion = line.extract(httpBegin + 5);
} else {
send400(&evtTimeout);
return false;
}
- if ((HttpVersion != "1.0") && (HttpVersion != "1.1")) {
+ if ((httpVersion != "1.0") && (httpVersion != "1.1")) {
send400(&evtTimeout);
return false;
}
@@ -168,7 +203,7 @@ bool Balau::HttpWorker::handleClient() {
value.trim();
- HttpHeaders[key] = value;
+ httpHeaders[key] = value;
}
} while(true);
@@ -179,9 +214,9 @@ bool Balau::HttpWorker::handleClient() {
if (method == Http::POST) {
int lengthStr = 0;
- HttpHeaders_t::iterator i = HttpHeaders.find("Content-Length");
+ StringMap::iterator i = httpHeaders.find("Content-Length");
- if (i != HttpHeaders.end())
+ if (i != httpHeaders.end())
lengthStr = i->second.to_int();
m_postData = (uint8_t *) malloc(lengthStr);
@@ -196,10 +231,10 @@ bool Balau::HttpWorker::handleClient() {
}
}
- if (HttpVersion == "1.1") {
- HttpHeaders_t::iterator i = HttpHeaders.find("Connection");
+ if (httpVersion == "1.1") {
+ StringMap::iterator i = httpHeaders.find("Connection");
- if (i != HttpHeaders.end()) {
+ if (i != httpHeaders.end()) {
if (i->second != "close") {
send400(&evtTimeout);
return false;
@@ -209,6 +244,57 @@ bool Balau::HttpWorker::handleClient() {
}
}
+ int variablesPos = uri.strchr('?');
+
+ if (variablesPos >= 0) {
+ char * variablesStr = uri.strdup(variablesPos + 1);
+ char * p = variablesStr;
+ char * ampPos;
+ uri = httpUnescape(uri.extract(0, variablesPos).to_charp());
+
+ do {
+ ampPos = strchr(p, '&');
+ if (ampPos)
+ *ampPos = 0;
+
+ char * val = strchr(p, '=');
+
+ if (val) {
+ *val++ = 0;
+ }
+ String keyStr = httpUnescape(p);
+ String valStr = val ? httpUnescape(val) : String("");
+ variables[keyStr] = valStr;
+
+ p = ampPos + 1;
+ } while (ampPos);
+
+ free(variablesStr);
+ }
+
+ if (uri.extract(0, 7) == "http://") {
+ int hostEnd = uri.strchr('/', 7);
+
+ if (hostEnd < 0) {
+ host = uri.extract(7);
+ uri = "/";
+ } else {
+ host = uri.extract(7, hostEnd - 7);
+ uri = uri.extract(hostEnd + 1);
+ }
+ }
+
+ StringMap::iterator hostIter = httpHeaders.find("host");
+
+ if (hostIter != httpHeaders.end()) {
+ if (host != "") {
+ send400(&evtTimeout);
+ return false;
+ }
+
+ host = hostIter->second;
+ }
+
// process query; everything should be here now