Clean client main handler function
This commit is contained in:
599
src/client.cpp
599
src/client.cpp
@ -221,296 +221,10 @@ bool connection_handler(const char *preprefix, const char *col1, const char *col
|
||||
bool error = false;
|
||||
char buffer[1024];
|
||||
char *prefix = (char *) preprefix;
|
||||
|
||||
HttpConnection *req = nullptr;
|
||||
try {
|
||||
HttpConnection req(socket);
|
||||
try {
|
||||
if (req.isExistingField("Connection") && req.getField("Connection") == "keep-alive") {
|
||||
req.setField("Connection", "keep-alive");
|
||||
req.setField("Keep-Alive", "timeout=3600, max=100");
|
||||
} else {
|
||||
req.setField("Connection", "close");
|
||||
error = true;
|
||||
}
|
||||
|
||||
string host = "";
|
||||
|
||||
if (!req.isExistingField("Host")) {
|
||||
req.respond(400);
|
||||
} else {
|
||||
host = req.getField("Host");
|
||||
long pos = host.find(':');
|
||||
if (pos != string::npos) {
|
||||
host.erase(pos, host.length() - pos);
|
||||
}
|
||||
|
||||
/*FILE *name = popen(("dig @8.8.8.8 +time=1 -x " + socket->getPeerAddress()->toString() +
|
||||
" | grep -oP \"^[^;].*\\t\\K([^ ]*)\\w\"").c_str(), "r");
|
||||
char hostbuffer[1024];
|
||||
memset(hostbuffer, 0, 1024);
|
||||
size_t size = fread(hostbuffer, 1, 1024, name);
|
||||
hostbuffer[size - 1] = 0; // remove \n
|
||||
if (size <= 1) {
|
||||
sprintf(hostbuffer, "%s", socket->getPeerAddress()->toString().c_str());
|
||||
}*/
|
||||
|
||||
sprintf(buffer, "[\x1B[1m%s\x1B[0m][%i]%s[%s][%i]%s ", host.c_str(), socket->getSocketPort(), col1,
|
||||
info->host.c_str(), socket->getPeerPort(), col2);
|
||||
prefix = buffer;
|
||||
|
||||
log(prefix, "\x1B[1m" + req.getMethod() + " " + req.getPath() + "\x1B[0m");
|
||||
log_to_file(prefix, "\x1B[1m" + req.getMethod() + " " + req.getPath() + "\x1B[0m", host);
|
||||
|
||||
bool noRedirect = req.getPath().find("/.well-known/") == 0 || (req.getPath().find("/files/") == 0);
|
||||
|
||||
bool redir = true;
|
||||
if (!noRedirect) {
|
||||
if (getWebRoot(host).empty()) {
|
||||
req.redirect(303, "https://www.necronda.net" + req.getPath());
|
||||
} else if (socket->getSocketPort() != 443) {
|
||||
req.redirect(302, "https://" + host + req.getPath());
|
||||
} else {
|
||||
redir = false;
|
||||
}
|
||||
} else {
|
||||
redir = false;
|
||||
}
|
||||
|
||||
URI path = URI(getWebRoot(host), req.getPath());
|
||||
pid_t childpid = 0;
|
||||
|
||||
if (redir) {
|
||||
|
||||
} else if (!path.getNewPath().empty() && req.getMethod() != "POST") {
|
||||
req.redirect(303, path.getNewPath());
|
||||
} else {
|
||||
FILE *file = path.openFile();
|
||||
if (file == nullptr) {
|
||||
req.setField("Cache-Control", "public, max-age=60");
|
||||
req.respond(404);
|
||||
} else {
|
||||
string type = path.getFileType();
|
||||
|
||||
if (type.find("inode/") == 0) {
|
||||
req.respond(403);
|
||||
} else if (path.getRelativeFilePath().find("/.") != string::npos && !noRedirect) {
|
||||
req.respond(403);
|
||||
} else {
|
||||
req.setField("Content-Type", type);
|
||||
req.setField("Last-Modified", getHttpDate(path.getFilePath()));
|
||||
|
||||
bool invalidMethod = false;
|
||||
bool etag = false;
|
||||
|
||||
if (path.isStatic()) {
|
||||
string hash = getETag(path.getFilePath());
|
||||
req.setField("ETag", hash);
|
||||
req.setField("Accept-Ranges", "bytes");
|
||||
if (type.find("text/") == 0) {
|
||||
req.setField("Cache-Control", "public, max-age=3600");
|
||||
} else {
|
||||
req.setField("Cache-Control", "public, max-age=86400");
|
||||
}
|
||||
req.setField("Allow", "GET");
|
||||
if (req.getMethod() != "GET") {
|
||||
invalidMethod = true;
|
||||
}
|
||||
if (req.isExistingField("If-None-Match") && req.getField("If-None-Match") == hash) {
|
||||
etag = true;
|
||||
}
|
||||
} else {
|
||||
req.setField("Accept-Ranges", "none");
|
||||
req.setField("Cache-Control", "private, no-cache");
|
||||
req.setField("Allow", "GET, POST, PUT");
|
||||
if (req.getMethod() != "GET" && req.getMethod() != "POST" && req.getMethod() != "PUT") {
|
||||
invalidMethod = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidMethod) {
|
||||
req.respond(405);
|
||||
} else if (etag) {
|
||||
req.respond(304);
|
||||
} else {
|
||||
int statuscode = 0;
|
||||
if (!path.isStatic()) {
|
||||
string cmd = (string) "env -i" +
|
||||
" REDIRECT_STATUS=" + cli_encode("CGI") +
|
||||
" DOCUMENT_ROOT=" + cli_encode(getWebRoot(host)) +
|
||||
" " + req.cgiExport() +
|
||||
(req.isExistingField("Content-Length") ? " CONTENT_LENGTH=" +
|
||||
cli_encode(req.getField(
|
||||
"Content-Length"))
|
||||
: "") +
|
||||
(req.isExistingField("Content-Type") ? " CONTENT_TYPE=" + cli_encode(
|
||||
req.getField("Content-Type")) : "") +
|
||||
((socket->isSecured()) ? " HTTPS=on" : "") +
|
||||
" PATH_INFO=" + cli_encode(path.getFilePathInfo()) +
|
||||
" PATH_TRANSLATED=" + cli_encode(path.getAbsolutePath()) +
|
||||
" QUERY_STRING=" + cli_encode(path.getQuery()) +
|
||||
" REMOTE_ADDR=" + cli_encode(socket->getPeerAddress()->toString()) +
|
||||
" REMOTE_HOST=" + cli_encode(info->host) +
|
||||
" REMOTE_PORT=" + cli_encode(to_string(socket->getPeerPort())) +
|
||||
" REQUEST_METHOD=" + cli_encode(req.getMethod()) +
|
||||
" REQUEST_URI=" + cli_encode(req.getPath()) +
|
||||
" SCRIPT_FILENAME=" + cli_encode(path.getFilePath()) +
|
||||
" SCRIPT_NAME=" + cli_encode(path.getRelativePath()) +
|
||||
" SERVER_ADMIN=" + cli_encode("lorenz.stechauner@gmail.com") +
|
||||
" SERVER_NAME=" + cli_encode(host) +
|
||||
" SERVER_PORT=" + cli_encode(to_string(socket->getSocketPort())) +
|
||||
" SERVER_SOFTWARE=" + cli_encode("Necronda 3.0") +
|
||||
" SERVER_PROTOCOL=" + cli_encode("HTTP/1.1") +
|
||||
" GATEWAY_INTERFACE=" + cli_encode("CGI/1.1") +
|
||||
" /usr/bin/php-cgi";
|
||||
|
||||
stds pipes = procopen(cmd.c_str());
|
||||
childpid = pipes.pid;
|
||||
|
||||
long len = req.isExistingField("Content-Length") ? strtol(req.getField("Content-Length").c_str(), nullptr, 10) : (req.getMethod() == "POST" || req.getMethod() == "PUT")?-1:0;
|
||||
socket->receive(pipes.stdin, len);
|
||||
fclose(pipes.stdin);
|
||||
|
||||
thread *t = new thread(php_error_handler, prefix, pipes.stderr);
|
||||
|
||||
string line;
|
||||
while (!(line = read_line(pipes.stdout)).empty()) {
|
||||
long pos = line.find(':');
|
||||
string index = line.substr(0, pos);
|
||||
string data = line.substr(pos + 1, line.length() - pos);
|
||||
|
||||
while (index[0] == ' ') index.erase(index.begin() + 0);
|
||||
while (index[index.length() - 1] == ' ') index.erase(index.end() - 1);
|
||||
while (data[0] == ' ') data.erase(data.begin() + 0);
|
||||
while (data[data.length() - 1] == ' ') data.erase(data.end() - 1);
|
||||
|
||||
if (index == "Status") {
|
||||
statuscode = (int) strtol(data.substr(0, 3).c_str(), nullptr, 10);
|
||||
} else {
|
||||
if (index == "Location" && statuscode == 0) {
|
||||
statuscode = 303;
|
||||
} else if (index == "Content-Type") {
|
||||
type = data;
|
||||
}
|
||||
req.setField(index, data);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
int c = fgetc(pipes.stdout);
|
||||
if (c == -1) {
|
||||
// No Data -> Error
|
||||
req.respond((statuscode == 0) ? 500 : statuscode);
|
||||
statuscode = -1;
|
||||
} else {
|
||||
ungetc(c, pipes.stdout);
|
||||
}
|
||||
file = pipes.stdout;
|
||||
}
|
||||
|
||||
if (statuscode != -1) {
|
||||
statuscode = (statuscode == 0) ? 200 : statuscode;
|
||||
|
||||
bool compress = (type.find("text/") == 0 ||
|
||||
(type.find("application/") == 0 && type.find("+xml") != string::npos) ||
|
||||
type == "application/json" ||
|
||||
type == "application/javascript") &&
|
||||
req.isExistingField("Accept-Encoding") &&
|
||||
req.getField("Accept-Encoding").find("deflate") != string::npos;
|
||||
|
||||
if (compress) {
|
||||
req.setField("Accept-Ranges", "none");
|
||||
}
|
||||
|
||||
if (compress && req.isExistingField("Range")) {
|
||||
req.respond(416);
|
||||
} else if (req.isExistingField("Range")) {
|
||||
string range = req.getField("Range");
|
||||
if (range.find("bytes=") != 0 || !path.isStatic()) {
|
||||
req.respond(416);
|
||||
} else {
|
||||
fseek(file, 0L, SEEK_END);
|
||||
long len = ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
long p = range.find('-');
|
||||
if (p == string::npos) {
|
||||
req.respond(416);
|
||||
} else {
|
||||
string part1 = range.substr(6, (unsigned long) (p - 6));
|
||||
string part2 = range.substr((unsigned long) (p + 1),
|
||||
range.length() - p - 1);
|
||||
long num1 = stol(part1, nullptr, 10);
|
||||
long num2 = len - 1;
|
||||
if (!part2.empty()) {
|
||||
num2 = stol(part2, nullptr, 10);
|
||||
}
|
||||
if (num1 < 0 || num1 >= len || num2 < 0 || num2 >= len) {
|
||||
req.respond(416);
|
||||
} else {
|
||||
req.setField("Content-Range",
|
||||
(string) "bytes " + to_string(num1) + "-" +
|
||||
to_string(num2) +
|
||||
"/" + to_string(len));
|
||||
req.respond(206, file, compress, num1, num2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
req.respond(statuscode, file, compress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
if (childpid > 0) {
|
||||
waitpid(childpid, nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HttpStatusCode status = req.getStatusCode();
|
||||
int code = status.code;
|
||||
string color = "";
|
||||
string comment = "";
|
||||
if ((code >= 200 && code < 300) || code == 304) {
|
||||
color = "\x1B[1;32m"; // Success (Cached): Green
|
||||
} else if (code >= 100 && code < 200) {
|
||||
color = "\x1B[1;93m"; // Continue: Yellow
|
||||
} else if (code >= 300 && code < 400) {
|
||||
color = "\x1B[1;93m"; // Redirect: Yellow
|
||||
comment = " -> " +
|
||||
(req.isExistingResponseField("Location") ? req.getResponseField("Location") : "<invalid>");
|
||||
} else if (code >= 400 && code < 500) {
|
||||
color = "\x1B[1;31m"; // Client Error: Red
|
||||
//comment = " -> " + req.getPath();
|
||||
} else if (code >= 500 & code < 600) {
|
||||
color = "\x1B[1;31m"; // Server Error: Red
|
||||
//comment = " -> " + req.getPath();
|
||||
}
|
||||
string msg = color + to_string(status.code) + " " + status.message + comment + " (" + formatTime(req.getDuration()) + ")\x1B[0m";
|
||||
log(prefix, msg);
|
||||
if (!host.empty()) {
|
||||
log_to_file(prefix, msg, host);
|
||||
}
|
||||
} catch (char *msg) {
|
||||
HttpStatusCode status = req.getStatusCode();
|
||||
log(prefix, to_string(status.code) + " " + status.message + " (" + formatTime(req.getDuration()) + ")");
|
||||
try {
|
||||
if (strncmp(msg, "timeout", strlen(msg)) == 0) {
|
||||
log(prefix, "Timeout!");
|
||||
req.setField("Connection", "close");
|
||||
req.respond(408);
|
||||
error = true;
|
||||
} else if (strncmp(msg, "Invalid path", strlen(msg)) == 0) {
|
||||
log(prefix, "Timeout!");
|
||||
req.setField("Connection", "close");
|
||||
req.respond(400);
|
||||
} else {
|
||||
log(prefix, (string) "Unable to receive from socket: " + msg);
|
||||
error = true;
|
||||
}
|
||||
} catch (char *msg2) {
|
||||
|
||||
}
|
||||
}
|
||||
*req = HttpConnection(socket);
|
||||
} catch (char *msg) {
|
||||
try {
|
||||
if (msg == "Malformed header") {
|
||||
@ -529,6 +243,313 @@ bool connection_handler(const char *preprefix, const char *col1, const char *col
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
bool noRedirect, redir, invalidMethod, etag;
|
||||
URI *path;
|
||||
pid_t childpid;
|
||||
FILE *file;
|
||||
int statuscode;
|
||||
string hash, type, host;
|
||||
thread *t;
|
||||
long pos;
|
||||
|
||||
if (req->isExistingField("Connection") && req->getField("Connection") == "keep-alive") {
|
||||
req->setField("Connection", "keep-alive");
|
||||
req->setField("Keep-Alive", "timeout=3600, max=100");
|
||||
} else {
|
||||
req->setField("Connection", "close");
|
||||
error = true;
|
||||
}
|
||||
|
||||
host = "";
|
||||
|
||||
if (!req->isExistingField("Host")) {
|
||||
req->respond(400);
|
||||
goto respond;
|
||||
}
|
||||
host = req->getField("Host");
|
||||
pos = host.find(':');
|
||||
if (pos != string::npos) {
|
||||
host.erase(pos, host.length() - pos);
|
||||
}
|
||||
|
||||
/*FILE *name = popen(("dig @8.8.8.8 +time=1 -x " + socket->getPeerAddress()->toString() +
|
||||
" | grep -oP \"^[^;].*\\t\\K([^ ]*)\\w\"").c_str(), "r");
|
||||
char hostbuffer[1024];
|
||||
memset(hostbuffer, 0, 1024);
|
||||
size_t size = fread(hostbuffer, 1, 1024, name);
|
||||
hostbuffer[size - 1] = 0; // remove \n
|
||||
if (size <= 1) {
|
||||
sprintf(hostbuffer, "%s", socket->getPeerAddress()->toString().c_str());
|
||||
}*/
|
||||
|
||||
sprintf(buffer, "[\x1B[1m%s\x1B[0m][%i]%s[%s][%i]%s ", host.c_str(), socket->getSocketPort(), col1,
|
||||
info->host.c_str(), socket->getPeerPort(), col2);
|
||||
prefix = buffer;
|
||||
|
||||
log(prefix, "\x1B[1m" + req->getMethod() + " " + req->getPath() + "\x1B[0m");
|
||||
log_to_file(prefix, "\x1B[1m" + req->getMethod() + " " + req->getPath() + "\x1B[0m", host);
|
||||
|
||||
noRedirect = req->getPath().find("/.well-known/") == 0 || (req->getPath().find("/files/") == 0);
|
||||
|
||||
redir = true;
|
||||
if (!noRedirect) {
|
||||
if (getWebRoot(host).empty()) {
|
||||
req->redirect(303, "https://www.necronda.net" + req->getPath());
|
||||
} else if (socket->getSocketPort() != 443) {
|
||||
req->redirect(302, "https://" + host + req->getPath());
|
||||
} else {
|
||||
redir = false;
|
||||
}
|
||||
} else {
|
||||
redir = false;
|
||||
}
|
||||
|
||||
*path = URI(getWebRoot(host), req->getPath());
|
||||
childpid = 0;
|
||||
|
||||
if (redir) {
|
||||
goto respond;
|
||||
} else if (!path->getNewPath().empty() && req->getMethod() != "POST") {
|
||||
req->redirect(303, path->getNewPath());
|
||||
goto respond;
|
||||
}
|
||||
|
||||
file = path->openFile();
|
||||
if (file == nullptr) {
|
||||
req->setField("Cache-Control", "public, max-age=60");
|
||||
req->respond(404);
|
||||
goto respond;
|
||||
}
|
||||
type = path->getFileType();
|
||||
|
||||
if (type.find("inode/") == 0) {
|
||||
req->respond(403);
|
||||
goto respond;
|
||||
} else if (path->getRelativeFilePath().find("/.") != string::npos && !noRedirect) {
|
||||
req->respond(403);
|
||||
goto respond;
|
||||
}
|
||||
|
||||
req->setField("Content-Type", type);
|
||||
req->setField("Last-Modified", getHttpDate(path->getFilePath()));
|
||||
|
||||
invalidMethod = false;
|
||||
etag = false;
|
||||
|
||||
if (path->isStatic()) {
|
||||
hash = getETag(path->getFilePath());
|
||||
req->setField("ETag", hash);
|
||||
req->setField("Accept-Ranges", "bytes");
|
||||
if (type.find("text/") == 0) {
|
||||
req->setField("Cache-Control", "public, max-age=3600");
|
||||
} else {
|
||||
req->setField("Cache-Control", "public, max-age=86400");
|
||||
}
|
||||
req->setField("Allow", "GET");
|
||||
if (req->getMethod() != "GET") {
|
||||
invalidMethod = true;
|
||||
}
|
||||
if (req->isExistingField("If-None-Match") && req->getField("If-None-Match") == hash) {
|
||||
etag = true;
|
||||
}
|
||||
} else {
|
||||
req->setField("Accept-Ranges", "none");
|
||||
req->setField("Cache-Control", "private, no-cache");
|
||||
req->setField("Allow", "GET, POST, PUT");
|
||||
if (req->getMethod() != "GET" && req->getMethod() != "POST" && req->getMethod() != "PUT") {
|
||||
invalidMethod = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidMethod) {
|
||||
req->respond(405);
|
||||
goto respond;
|
||||
} else if (etag) {
|
||||
req->respond(304);
|
||||
goto respond;
|
||||
}
|
||||
|
||||
statuscode = 0;
|
||||
if (!path->isStatic()) {
|
||||
string cmd = (string) "env -i" +
|
||||
" REDIRECT_STATUS=" + cli_encode("CGI") +
|
||||
" DOCUMENT_ROOT=" + cli_encode(getWebRoot(host)) +
|
||||
" " + req->cgiExport() +
|
||||
(req->isExistingField("Content-Length") ? " CONTENT_LENGTH=" +
|
||||
cli_encode(req->getField(
|
||||
"Content-Length"))
|
||||
: "") +
|
||||
(req->isExistingField("Content-Type") ? " CONTENT_TYPE=" + cli_encode(
|
||||
req->getField("Content-Type")) : "") +
|
||||
((socket->isSecured()) ? " HTTPS=on" : "") +
|
||||
" PATH_INFO=" + cli_encode(path->getFilePathInfo()) +
|
||||
" PATH_TRANSLATED=" + cli_encode(path->getAbsolutePath()) +
|
||||
" QUERY_STRING=" + cli_encode(path->getQuery()) +
|
||||
" REMOTE_ADDR=" + cli_encode(socket->getPeerAddress()->toString()) +
|
||||
" REMOTE_HOST=" + cli_encode(info->host) +
|
||||
" REMOTE_PORT=" + cli_encode(to_string(socket->getPeerPort())) +
|
||||
" REQUEST_METHOD=" + cli_encode(req->getMethod()) +
|
||||
" REQUEST_URI=" + cli_encode(req->getPath()) +
|
||||
" SCRIPT_FILENAME=" + cli_encode(path->getFilePath()) +
|
||||
" SCRIPT_NAME=" + cli_encode(path->getRelativePath()) +
|
||||
" SERVER_ADMIN=" + cli_encode("lorenz.stechauner@gmail.com") +
|
||||
" SERVER_NAME=" + cli_encode(host) +
|
||||
" SERVER_PORT=" + cli_encode(to_string(socket->getSocketPort())) +
|
||||
" SERVER_SOFTWARE=" + cli_encode("Necronda 3.0") +
|
||||
" SERVER_PROTOCOL=" + cli_encode("HTTP/1.1") +
|
||||
" GATEWAY_INTERFACE=" + cli_encode("CGI/1.1") +
|
||||
" /usr/bin/php-cgi";
|
||||
|
||||
stds pipes = procopen(cmd.c_str());
|
||||
childpid = pipes.pid;
|
||||
|
||||
long len = req->isExistingField("Content-Length") ? strtol(req->getField("Content-Length").c_str(), nullptr, 10) : (req->getMethod() == "POST" || req->getMethod() == "PUT")?-1:0;
|
||||
socket->receive(pipes.stdin, len);
|
||||
fclose(pipes.stdin);
|
||||
|
||||
t = new thread(php_error_handler, prefix, pipes.stderr);
|
||||
|
||||
string line;
|
||||
while (!(line = read_line(pipes.stdout)).empty()) {
|
||||
long pos = line.find(':');
|
||||
string index = line.substr(0, pos);
|
||||
string data = line.substr(pos + 1, line.length() - pos);
|
||||
|
||||
while (index[0] == ' ') index.erase(index.begin() + 0);
|
||||
while (index[index.length() - 1] == ' ') index.erase(index.end() - 1);
|
||||
while (data[0] == ' ') data.erase(data.begin() + 0);
|
||||
while (data[data.length() - 1] == ' ') data.erase(data.end() - 1);
|
||||
|
||||
if (index == "Status") {
|
||||
statuscode = (int) strtol(data.substr(0, 3).c_str(), nullptr, 10);
|
||||
} else {
|
||||
if (index == "Location" && statuscode == 0) {
|
||||
statuscode = 303;
|
||||
} else if (index == "Content-Type") {
|
||||
type = data;
|
||||
}
|
||||
req->setField(index, data);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
int c = fgetc(pipes.stdout);
|
||||
if (c == -1) {
|
||||
// No Data -> Error
|
||||
req->respond((statuscode == 0) ? 500 : statuscode);
|
||||
statuscode = -1;
|
||||
} else {
|
||||
ungetc(c, pipes.stdout);
|
||||
}
|
||||
file = pipes.stdout;
|
||||
}
|
||||
|
||||
if (statuscode != -1) {
|
||||
statuscode = (statuscode == 0) ? 200 : statuscode;
|
||||
|
||||
bool compress = (type.find("text/") == 0 ||
|
||||
(type.find("application/") == 0 && type.find("+xml") != string::npos) ||
|
||||
type == "application/json" ||
|
||||
type == "application/javascript") &&
|
||||
req->isExistingField("Accept-Encoding") &&
|
||||
req->getField("Accept-Encoding").find("deflate") != string::npos;
|
||||
|
||||
if (compress) {
|
||||
req->setField("Accept-Ranges", "none");
|
||||
}
|
||||
|
||||
if (compress && req->isExistingField("Range")) {
|
||||
req->respond(416);
|
||||
} else if (req->isExistingField("Range")) {
|
||||
string range = req->getField("Range");
|
||||
if (range.find("bytes=") != 0 || !path->isStatic()) {
|
||||
req->respond(416);
|
||||
} else {
|
||||
fseek(file, 0L, SEEK_END);
|
||||
long len = ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
long p = range.find('-');
|
||||
if (p == string::npos) {
|
||||
req->respond(416);
|
||||
} else {
|
||||
string part1 = range.substr(6, (unsigned long) (p - 6));
|
||||
string part2 = range.substr((unsigned long) (p + 1),
|
||||
range.length() - p - 1);
|
||||
long num1 = stol(part1, nullptr, 10);
|
||||
long num2 = len - 1;
|
||||
if (!part2.empty()) {
|
||||
num2 = stol(part2, nullptr, 10);
|
||||
}
|
||||
if (num1 < 0 || num1 >= len || num2 < 0 || num2 >= len) {
|
||||
req->respond(416);
|
||||
} else {
|
||||
req->setField("Content-Range",
|
||||
(string) "bytes " + to_string(num1) + "-" +
|
||||
to_string(num2) +
|
||||
"/" + to_string(len));
|
||||
req->respond(206, file, compress, num1, num2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
req->respond(statuscode, file, compress);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
if (childpid > 0) {
|
||||
waitpid(childpid, nullptr, 0);
|
||||
}
|
||||
|
||||
respond:
|
||||
|
||||
HttpStatusCode status = req->getStatusCode();
|
||||
int code = status.code;
|
||||
string color = "";
|
||||
string comment = "";
|
||||
if ((code >= 200 && code < 300) || code == 304) {
|
||||
color = "\x1B[1;32m"; // Success (Cached): Green
|
||||
} else if (code >= 100 && code < 200) {
|
||||
color = "\x1B[1;93m"; // Continue: Yellow
|
||||
} else if (code >= 300 && code < 400) {
|
||||
color = "\x1B[1;93m"; // Redirect: Yellow
|
||||
comment = " -> " +
|
||||
(req->isExistingResponseField("Location") ? req->getResponseField("Location") : "<invalid>");
|
||||
} else if (code >= 400 && code < 500) {
|
||||
color = "\x1B[1;31m"; // Client Error: Red
|
||||
//comment = " -> " + req->getPath();
|
||||
} else if (code >= 500 & code < 600) {
|
||||
color = "\x1B[1;31m"; // Server Error: Red
|
||||
//comment = " -> " + req->getPath();
|
||||
}
|
||||
string msg = color + to_string(status.code) + " " + status.message + comment + " (" + formatTime(req->getDuration()) + ")\x1B[0m";
|
||||
log(prefix, msg);
|
||||
if (!host.empty()) {
|
||||
log_to_file(prefix, msg, host);
|
||||
}
|
||||
} catch (char *msg) {
|
||||
HttpStatusCode status = req->getStatusCode();
|
||||
log(prefix, to_string(status.code) + " " + status.message + " (" + formatTime(req->getDuration()) + ")");
|
||||
try {
|
||||
if (strncmp(msg, "timeout", strlen(msg)) == 0) {
|
||||
log(prefix, "Timeout!");
|
||||
req->setField("Connection", "close");
|
||||
req->respond(408);
|
||||
error = true;
|
||||
} else if (strncmp(msg, "Invalid path", strlen(msg)) == 0) {
|
||||
log(prefix, "Timeout!");
|
||||
req->setField("Connection", "close");
|
||||
req->respond(400);
|
||||
} else {
|
||||
log(prefix, (string) "Unable to receive from socket: " + msg);
|
||||
error = true;
|
||||
}
|
||||
} catch (char *msg2) {
|
||||
|
||||
}
|
||||
}
|
||||
return !error;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user