|
|
|
@ -1,48 +1,23 @@
|
|
|
|
|
#include "csoap/http_request_handler.h"
|
|
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#if CSOAP_ENABLE_OUTPUT
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "csoap/common.h"
|
|
|
|
|
#include "csoap/http_request.h"
|
|
|
|
|
#include "csoap/http_response.h"
|
|
|
|
|
#include "csoap/soap_request.h"
|
|
|
|
|
#include "csoap/soap_response.h"
|
|
|
|
|
#include "csoap/soap_service.h"
|
|
|
|
|
|
|
|
|
|
namespace csoap {
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
// Perform URL-decoding on a string. Returns false if the encoding was invalid.
|
|
|
|
|
static bool UrlDecode(const std::string& in, std::string& out) {
|
|
|
|
|
out.clear();
|
|
|
|
|
out.reserve(in.size());
|
|
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < in.size(); ++i) {
|
|
|
|
|
if (in[i] == '%') {
|
|
|
|
|
if (i + 3 <= in.size()) {
|
|
|
|
|
int value = 0;
|
|
|
|
|
std::istringstream is(in.substr(i + 1, 2));
|
|
|
|
|
if (is >> std::hex >> value) {
|
|
|
|
|
out += static_cast<char>(value);
|
|
|
|
|
i += 2;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else if (in[i] == '+') {
|
|
|
|
|
out += ' ';
|
|
|
|
|
} else {
|
|
|
|
|
out += in[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
HttpRequestHandler::HttpRequestHandler() {
|
|
|
|
|
// Create worker threads.
|
|
|
|
|
for (std::size_t i = 0; i < 2; ++i) {
|
|
|
|
|
workers_.create_thread(std::bind(&HttpRequestHandler::WorkerRoutine, this));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool HttpRequestHandler::RegisterService(SoapServicePtr soap_service) {
|
|
|
|
@ -57,6 +32,7 @@ bool HttpRequestHandler::RegisterService(SoapServicePtr soap_service) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
void HttpRequestHandler::HandleRequest(const HttpRequest& http_request,
|
|
|
|
|
HttpResponse* http_response) {
|
|
|
|
|
// Parse the SOAP request XML.
|
|
|
|
@ -81,28 +57,69 @@ void HttpRequestHandler::HandleRequest(const HttpRequest& http_request,
|
|
|
|
|
http_response->SetContentType(kTextXmlUtf8);
|
|
|
|
|
http_response->SetContentLength(content.length());
|
|
|
|
|
http_response->set_content(std::move(content));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
// Decode URL to path.
|
|
|
|
|
std::string request_path;
|
|
|
|
|
if (!UrlDecode(request.uri, request_path)) {
|
|
|
|
|
reply = HttpReply::StockReply(HttpReply::BAD_REQUEST);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
void HttpRequestHandler::Enqueue(ConnectionPtr conn) {
|
|
|
|
|
queue_.Put(conn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Request path must be absolute and not contain "..".
|
|
|
|
|
if (request_path.empty() ||
|
|
|
|
|
request_path[0] != '/' ||
|
|
|
|
|
request_path.find("..") != std::string::npos) {
|
|
|
|
|
reply = HttpReply::StockReply(HttpReply::BAD_REQUEST);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
void HttpRequestHandler::StopWorkers() {
|
|
|
|
|
#if CSOAP_ENABLE_OUTPUT
|
|
|
|
|
std::cout << "Stopping workers...\n";
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// If path ends in slash (i.e. is a directory) then add "index.html".
|
|
|
|
|
if (request_path[request_path.size() - 1] == '/') {
|
|
|
|
|
request_path += "index.html";
|
|
|
|
|
}
|
|
|
|
|
// Enqueue an null connection to trigger the first worker to stop.
|
|
|
|
|
queue_.Put(ConnectionPtr());
|
|
|
|
|
|
|
|
|
|
workers_.join_all();
|
|
|
|
|
|
|
|
|
|
#if CSOAP_ENABLE_OUTPUT
|
|
|
|
|
std::cout << "Workers have been stopped.\n";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: How and when to exit?
|
|
|
|
|
void HttpRequestHandler::WorkerRoutine() {
|
|
|
|
|
for (;;) {
|
|
|
|
|
ConnectionPtr conn = queue_.Get();
|
|
|
|
|
|
|
|
|
|
if (!conn) {
|
|
|
|
|
#if CSOAP_ENABLE_OUTPUT
|
|
|
|
|
boost::thread::id thread_id = boost::this_thread::get_id();
|
|
|
|
|
std::cout << "Worker is going to stop (thread: " << thread_id << ")\n";
|
|
|
|
|
#endif
|
|
|
|
|
// For stopping next worker.
|
|
|
|
|
queue_.Put(ConnectionPtr());
|
|
|
|
|
// Stop the worker.
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse the SOAP request XML.
|
|
|
|
|
SoapRequest soap_request;
|
|
|
|
|
if (!soap_request.FromXml(conn->request_.content())) {
|
|
|
|
|
conn->response_.set_status(HttpStatus::BAD_REQUEST);
|
|
|
|
|
conn->DoWrite(); // TODO
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SoapResponse soap_response;
|
|
|
|
|
|
|
|
|
|
// TODO: Get service by URL.
|
|
|
|
|
for (SoapServicePtr& service : soap_services_) {
|
|
|
|
|
service->Handle(soap_request, &soap_response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string content;
|
|
|
|
|
soap_response.ToXml(&content);
|
|
|
|
|
|
|
|
|
|
conn->response_.set_status(HttpStatus::OK);
|
|
|
|
|
conn->response_.SetContentType(kTextXmlUtf8);
|
|
|
|
|
conn->response_.SetContentLength(content.length());
|
|
|
|
|
conn->response_.set_content(std::move(content));
|
|
|
|
|
|
|
|
|
|
conn->DoWrite();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace csoap
|
|
|
|
|