static int trySendFile(const std::string& realfile, HttpResponse& response) { std::ifstream ifs; ifs.open(realfile.c_str(), std::ifstream::in); // whether file not found if (!ifs.is_open()) { return 1; } VLOG(2) << "absolute file path: " << realfile; // get file length ifs.seekg(0, std::ios::end); int length = ifs.tellg(); ifs.seekg(0, std::ios::beg); // read file content std::string buff; buff.resize(length); ifs.read(const_cast<char*>(buff.data()), length); ifs.close(); response.setContent(buff); response.setStatus(HttpResponse::ok); std::string ext; std::string::size_type pos1 = realfile.rfind('.'); if (pos1 != realfile.npos) { ext = realfile.substr(pos1 + 1, realfile.length() - pos1 - 1); } auto& mime = HttpMime::getMimeFromExt(ext); response.addHeader("Content-Type", mime); return 0; }
void ShellHttpServlet::doPost(HttpRequest& request, HttpResponse& response) { char * tmpfile = tempnam("/tmp", "ecf_"); std::string script_file = tmpfile; free(tmpfile); std::ofstream ofs(script_file.c_str()); ofs << request.getBody(); ofs << std::endl; ofs.close(); LOG(INFO) << "file: " << script_file << ", script: " << request.getBody(); std::string stdout; { std::lock_guard<std::mutex> guard(lock); exec_command("bash", script_file, &stdout, NULL); } response.setContent(stdout); response.setStatus(idgs::httpserver::HttpResponse::ok); response.addHeader(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_TEXT_PLAIN); remove(script_file.c_str()); return; }
bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& response) { using namespace JsonRpc; response.addHeader("Content-Type", "application/json"); JsonRpcRequest jsonRequest; JsonRpcResponse jsonResponse; try { logger(TRACE) << "JSON-RPC request: " << request.getBody(); jsonRequest.parseRequest(request.getBody()); jsonResponse.setId(jsonRequest.getId()); // copy id static std::unordered_map<std::string, JsonMemberMethod> jsonRpcHandlers = { { "getblockcount", makeMemberMethod(&RpcServer::on_getblockcount) }, { "on_getblockhash", makeMemberMethod(&RpcServer::on_getblockhash) }, { "getblocktemplate", makeMemberMethod(&RpcServer::on_getblocktemplate) }, { "getcurrencyid", makeMemberMethod(&RpcServer::on_get_currency_id) }, { "submitblock", makeMemberMethod(&RpcServer::on_submitblock) }, { "getlastblockheader", makeMemberMethod(&RpcServer::on_get_last_block_header) }, { "getblockheaderbyhash", makeMemberMethod(&RpcServer::on_get_block_header_by_hash) }, { "getblockheaderbyheight", makeMemberMethod(&RpcServer::on_get_block_header_by_height) } }; auto it = jsonRpcHandlers.find(jsonRequest.getMethod()); if (it == jsonRpcHandlers.end()) { throw JsonRpcError(JsonRpc::errMethodNotFound); } if (jsonRequest.getMethod() != "getcurrencyid" && !checkCoreReady()) { throw JsonRpcError(CORE_RPC_ERROR_CODE_CORE_BUSY, "Core is busy"); } it->second(this, jsonRequest, jsonResponse); } catch (const JsonRpcError& err) { jsonResponse.setError(err); } catch (const std::exception& e) { jsonResponse.setError(JsonRpcError(JsonRpc::errInternalError, e.what())); } response.setBody(jsonResponse.getBody()); logger(TRACE) << "JSON-RPC response: " << jsonResponse.getBody(); return true; }
HttpResponse* listToResponse(HttpRequest* pRequest, const Rcpp::List& response) { using namespace Rcpp; if (response.isNULL() || response.size() == 0) return NULL; CharacterVector names = response.names(); int status = Rcpp::as<int>(response["status"]); std::string statusDesc = getStatusDescription(status); List responseHeaders = response["headers"]; // Self-frees when response is written DataSource* pDataSource = NULL; // The response can either contain: // - bodyFile: String value that names the file that should be streamed // - body: Character vector (which is charToRaw-ed) or raw vector, or NULL if (std::find(names.begin(), names.end(), "bodyFile") != names.end()) { FileDataSource* pFDS = new FileDataSource(); pFDS->initialize(Rcpp::as<std::string>(response["bodyFile"]), Rcpp::as<bool>(response["bodyFileOwned"])); pDataSource = pFDS; } else if (Rf_isString(response["body"])) { RawVector responseBytes = Function("charToRaw")(response["body"]); pDataSource = new RawVectorDataSource(responseBytes); } else { RawVector responseBytes = response["body"]; pDataSource = new RawVectorDataSource(responseBytes); } HttpResponse* pResp = new HttpResponse(pRequest, status, statusDesc, pDataSource); CharacterVector headerNames = responseHeaders.names(); for (R_len_t i = 0; i < responseHeaders.size(); i++) { pResp->addHeader( std::string((char*)headerNames[i], headerNames[i].size()), Rcpp::as<std::string>(responseHeaders[i])); } return pResp; }
int HttpRequest::_on_headers_complete(http_parser* pParser) { trace("on_headers_complete"); int result = 0; HttpResponse* pResp = _pWebApplication->onHeaders(this); if (pResp) { bool bodyExpected = _headers.find("Content-Length") != _headers.end() || _headers.find("Transfer-Encoding") != _headers.end(); if (bodyExpected) { // If we're expecting a request body and we're returning a response // prematurely, then add "Connection: close" header to the response and // set a flag to ignore all future reads on this connection. pResp->addHeader("Connection", "close"); uv_read_stop((uv_stream_t*)handle()); _ignoreNewData = true; } pResp->writeResponse(); // result = 1 has special meaning to http_parser for this one callback; it // means F_SKIPBODY should be set on the parser. That's not what we want // here; we just want processing to terminate. result = 2; } else { // If the request is Expect: Continue, and the app didn't say otherwise, // then give it what it wants if (_headers.find("Expect") != _headers.end() && _headers["Expect"] == "100-continue") { pResp = new HttpResponse(this, 100, "Continue", NULL); pResp->writeResponse(); } } // TODO: Allocate body return result; }
int HttpRequest::_on_headers_complete(http_parser* pParser) { trace("on_headers_complete"); int result = 0; HttpResponse* pResp = _pWebApplication->onHeaders(this); if (pResp) { bool bodyExpected = _headers.find("Content-Length") != _headers.end() || _headers.find("Transfer-Encoding") != _headers.end(); if (bodyExpected) { // If we're expecting a request body and we're returning a response // prematurely, then add "Connection: close" header to the response and // set a flag to ignore all future reads on this connection. pResp->addHeader("Connection", "close"); // Do not call uv_read_stop, it mysteriously seems to prevent the response // from being written. // uv_read_stop((uv_stream_t*)handle()); _ignoreNewData = true; } pResp->writeResponse(); result = 1; } else { // If the request is Expect: Continue, and the app didn't say otherwise, // then give it what it wants if (_headers.find("Expect") != _headers.end() && _headers["Expect"] == "100-continue") { pResp = new HttpResponse(this, 100, "Continue", NULL); pResp->writeResponse(); } } // TODO: Allocate body return result; }
void ProcessingThread::processFileDescriptor(int fd) { char buffer[1024*10]; // 10kb ssize_t count=1; while (count > 0) { count = read(fd, buffer, 1024*10); if (count < 1024*10) break; } HttpRequest req(buffer); HttpResponse resp; /*if (req.isKeepAlive()) { resp.addHeader("Connection","Keep-Alive"); }*/ if (req.getRequestURI().compare("/sum") == 0) { int a=0,b=0; const vector<QueryParameter*>& params = req.getParams(); for (unsigned i=0;i<params.size();i++) { if (params[i]->getParam().compare("a") == 0) a = atoi(params[i]->getValue().c_str()); if (params[i]->getParam().compare("b") == 0) b = atoi(params[i]->getValue().c_str()); } char buffer[128]; sprintf(buffer,"<html><body>%d + %d = %d</body></html>",a,b,a+b); char len[10]; sprintf(len,"%lu",strlen(buffer)); HttpResponse resp("HTTP/1.1 200 OK"); resp.addHeader("Content-Type","text/html; charset=utf-8"); resp.addHeader("Content-Length",len); resp.setContent(((void*)buffer),strlen(buffer)); resp.writeToFD(fd); } else if (!fileExists(req.getRequestURI().c_str())) { resp.setStatusLine("HTTP/1.1 404 Not found"); resp.addHeader("Content-Type","text/html; charset=utf-8"); resp.addHeader("Content-Length","50"); resp.setContent(((void*)"<html><body><h1>404 - Not found</h1></body></html>"),50); resp.writeToFD(fd); } else { if (isDir(req.getRequestURI().c_str())) { resp.setStatusLine("HTTP/1.1 200 OK"); resp.addHeader("Content-Type","text/html; charset=utf-8"); unsigned length = 0; string body = "<html><body>"; vector<string> files; dirLs(req.getRequestURI().c_str(),files); for (unsigned i=0;i<files.size();i++) { body += "<a href=\""+req.getRequestURI()+"/"+files[i]+"\">" + files[i] +"</a><br/>"; } length = body.length(); resp.setContent((void*)body.c_str(),length); char buff[10]; sprintf(buff,"%d",length); resp.addHeader("Content-Length",buff); resp.writeToFD(fd); } else if (isFile(req.getRequestURI().c_str())) { string fileExt = getExtension(req.getRequestURI()); if (fileExt != "lua") { ifstream file(req.getRequestURI().c_str()); file.seekg(0,ios_base::end); streamsize fileSize = file.tellg(); file.seekg(0,ios_base::beg); char* content = new char[fileSize]; file.read(content,fileSize); file.close(); char buff[10]; sprintf(buff,"%ld",fileSize); resp.setStatusLine("HTTP/1.1 200 OK"); resp.addHeader("Content-Length",buff); resp.setContent(content,fileSize); if (fileExt.compare("html") == 0) { resp.addHeader("Content-Type","text/html; charset=utf-8"); } resp.writeToFD(fd); delete [] content; } else { int result = luaL_loadfile(luaState,req.getRequestURI().c_str()); if (result != 0) { resp.setStatusLine("HTTP/1.1 500 Internal server error"); resp.addHeader("Content-Type","text/html; charset=utf-8"); char buffer[1024]; sprintf(buffer,"<html><body><h1>500 Internal server error</h1><br/><p>%s</p></body></html>",lua_tostring(luaState,1)); lua_pop(luaState,1); // pop the error message char lenBuff[10]; sprintf(lenBuff,"%lu",strlen(buffer)); resp.addHeader("Content-Length",lenBuff); resp.setContent(((void*)"<html><body><h1>404 - Not found</h1></body></html>"),strlen(buffer)); resp.writeToFD(fd); } else { // environment table - replaced with globals, setting up an environment that includes all the built-in functions is a pain //lua_newtable(luaState); // print function stringstream ss; //lua_pushstring(luaState,"print"); lua_pushlightuserdata(luaState,&ss); lua_pushcclosure(luaState,luaStdOutPrint,1); lua_setglobal(luaState,"print"); //lua_settable(luaState,-3); // headers table //lua_pushstring(luaState,"HTTP_HEADERS"); lua_newtable(luaState); const vector<HttpHeader*>& headers = req.getHeaders(); for (unsigned i=0;i<headers.size();i++) { lua_pushstring(luaState,headers[i]->getField().c_str()); lua_pushstring(luaState,headers[i]->getValue().c_str()); lua_settable(luaState,-3); } lua_setglobal(luaState,"HTTP_HEADERS"); //lua_settable(luaState,-3); // parameters table //lua_pushstring(luaState,"HTTP_QUERY_PARAMS"); lua_newtable(luaState); const vector<QueryParameter*>& params = req.getParams(); for (unsigned i=0;i<params.size();i++) { lua_pushstring(luaState,params[i]->getParam().c_str()); lua_pushstring(luaState,params[i]->getValue().c_str()); lua_settable(luaState,-3); } lua_setglobal(luaState,"HTTP_QUERY_PARAMS"); //lua_settable(luaState,-3); // set the environment //lua_setupvalue(luaState, -2, 1); result = lua_pcall(luaState,0,LUA_MULTRET,0); if (result == 0) { resp.setStatusLine("HTTP/1.1 200 OK"); resp.addHeader("Content-Type","text/html; charset=utf-8"); const string& output = ss.str(); char lenBuff[10]; sprintf(lenBuff,"%lu",output.length()); resp.addHeader("Content-Length",lenBuff); resp.setContent(((void*)output.c_str()),output.length()); resp.writeToFD(fd); } else if (result == LUA_ERRRUN || result == LUA_ERRMEM || result == LUA_ERRERR) { resp.setStatusLine("HTTP/1.1 500 Internal server error"); resp.addHeader("Content-Type","text/html; charset=utf-8"); char buffer[1024]; sprintf(buffer,"<html><body><h1>500 Internal server error</h1><br/><p>%s</p></body></html>",lua_tostring(luaState,1)); lua_pop(luaState,1); // pop the error message char lenBuff[10]; sprintf(lenBuff,"%lu",strlen(buffer)); resp.addHeader("Content-Length",lenBuff); resp.setContent(((void*)buffer),strlen(buffer)); resp.writeToFD(fd); } } } } } //if (!req.isKeepAlive()) close(fd); /*else karThread->update(fd,15);*/ }
void HttpRequest::_on_request_read(uv_stream_t*, ssize_t nread, uv_buf_t buf) { if (nread > 0) { //std::cerr << nread << " bytes read\n"; if (_ignoreNewData) { // Do nothing } else if (_protocol == HTTP) { int parsed = http_parser_execute(&_parser, &request_settings(), buf.base, nread); if (_parser.upgrade) { char* pData = buf.base + parsed; ssize_t pDataLen = nread - parsed; if (_headers.find("upgrade") != _headers.end() && _headers["upgrade"] == std::string("websocket") && _headers.find("sec-websocket-key") != _headers.end()) { // Freed in on_response_written HttpResponse* pResp = new HttpResponse(this, 101, "Switching Protocols", NULL); pResp->addHeader("Upgrade", "websocket"); pResp->addHeader("Connection", "Upgrade"); pResp->addHeader( "Sec-WebSocket-Accept", createHandshakeResponse(_headers["sec-websocket-key"])); // TODO: Consult app about supported WS protocol //pResp->addHeader("Sec-WebSocket-Protocol", ""); pResp->writeResponse(); _protocol = WebSockets; _pWebApplication->onWSOpen(this); read(pData, pDataLen); } if (_protocol != WebSockets) { // TODO: Write failure close(); } } else if (parsed < nread) { if (!_ignoreNewData) { fatal_error("on_request_read", "parse error"); uv_read_stop((uv_stream_t*)handle()); close(); } } } else if (_protocol == WebSockets) { read(buf.base, nread); } } else if (nread < 0) { uv_err_t err = uv_last_error(_pLoop); if (err.code == UV_EOF /*|| err.code == UV_ECONNRESET*/) { } else { fatal_error("on_request_read", uv_strerror(err)); } close(); } else { // It's normal for nread == 0, it's when uv requests a buffer then // decides it doesn't need it after all } free(buf.base); }