void process_request(http::request<request_body_t, http::basic_fields<alloc_t>> const& req) { switch (req.method()) { case http::verb::get: send_file(req.target()); break; default: // We return responses indicating an error if // we do not recognize the request method. send_bad_response( http::status::bad_request, "Invalid request-method '" + req.method_string().to_string() + "'\r\n"); break; } }
bool ConsoleHandler::HandleRequest( AsioTlsStream& stream, const ApiUser::Ptr& user, boost::beast::http::request<boost::beast::http::string_body>& request, const Url::Ptr& url, boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, boost::asio::yield_context& yc, HttpServerConnection& server ) { namespace http = boost::beast::http; if (url->GetPath().size() != 3) return false; if (request.method() != http::verb::post) return false; QueryDescription qd; String methodName = url->GetPath()[2]; FilterUtility::CheckPermission(user, "console"); String session = HttpUtility::GetLastParameter(params, "session"); if (session.IsEmpty()) session = Utility::NewUniqueID(); String command = HttpUtility::GetLastParameter(params, "command"); bool sandboxed = HttpUtility::GetLastParameter(params, "sandboxed"); if (methodName == "execute-script") return ExecuteScriptHelper(request, response, params, command, session, sandboxed); else if (methodName == "auto-complete-script") return AutocompleteScriptHelper(request, response, params, command, session, sandboxed); HttpUtility::SendJsonError(response, params, 400, "Invalid method specified: " + methodName); return true; }
bool EventsHandler::HandleRequest( AsioTlsStream& stream, const ApiUser::Ptr& user, boost::beast::http::request<boost::beast::http::string_body>& request, const Url::Ptr& url, boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, boost::asio::yield_context& yc, HttpServerConnection& server ) { namespace asio = boost::asio; namespace http = boost::beast::http; if (url->GetPath().size() != 2) return false; if (request.method() != http::verb::post) return false; if (request.version() == 10) { HttpUtility::SendJsonError(response, params, 400, "HTTP/1.0 not supported for event streams."); return true; } Array::Ptr types = params->Get("types"); if (!types) { HttpUtility::SendJsonError(response, params, 400, "'types' query parameter is required."); return true; } { ObjectLock olock(types); for (const String& type : types) { FilterUtility::CheckPermission(user, "events/" + type); } } String queueName = HttpUtility::GetLastParameter(params, "queue"); if (queueName.IsEmpty()) { HttpUtility::SendJsonError(response, params, 400, "'queue' query parameter is required."); return true; } std::set<EventType> eventTypes; { ObjectLock olock(types); for (const String& type : types) { auto typeId (l_EventTypes.find(type)); if (typeId != l_EventTypes.end()) { eventTypes.emplace(typeId->second); } } } EventsSubscriber subscriber (std::move(eventTypes), HttpUtility::GetLastParameter(params, "filter"), l_ApiQuery); server.StartStreaming(); response.result(http::status::ok); response.set(http::field::content_type, "application/json"); IoBoundWorkSlot dontLockTheIoThread (yc); http::async_write(stream, response, yc); stream.async_flush(yc); asio::const_buffer newLine ("\n", 1); for (;;) { auto event (subscriber.GetInbox()->Shift(yc)); if (event) { CpuBoundWork buildingResponse (yc); String body = JsonEncode(event); boost::algorithm::replace_all(body, "\n", ""); asio::const_buffer payload (body.CStr(), body.GetLength()); buildingResponse.Done(); asio::async_write(stream, payload, yc); asio::async_write(stream, newLine, yc); stream.async_flush(yc); } else if (server.Disconnected()) { return true; } } }
bool ActionsHandler::HandleRequest( AsioTlsStream& stream, const ApiUser::Ptr& user, boost::beast::http::request<boost::beast::http::string_body>& request, const Url::Ptr& url, boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, boost::asio::yield_context& yc, HttpServerConnection& server ) { namespace http = boost::beast::http; if (url->GetPath().size() != 3) return false; if (request.method() != http::verb::post) return false; String actionName = url->GetPath()[2]; ApiAction::Ptr action = ApiAction::GetByName(actionName); if (!action) { HttpUtility::SendJsonError(response, params, 404, "Action '" + actionName + "' does not exist."); return true; } QueryDescription qd; const std::vector<String>& types = action->GetTypes(); std::vector<Value> objs; String permission = "actions/" + actionName; if (!types.empty()) { qd.Types = std::set<String>(types.begin(), types.end()); qd.Permission = permission; try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { HttpUtility::SendJsonError(response, params, 404, "No objects found.", DiagnosticInformation(ex)); return true; } } else { FilterUtility::CheckPermission(user, permission); objs.emplace_back(nullptr); } ArrayData results; Log(LogNotice, "ApiActionHandler") << "Running action " << actionName; bool verbose = false; if (params) verbose = HttpUtility::GetLastParameter(params, "verbose"); for (const ConfigObject::Ptr& obj : objs) { try { results.emplace_back(action->Invoke(obj, params)); } catch (const std::exception& ex) { Dictionary::Ptr fail = new Dictionary({ { "code", 500 }, { "status", "Action execution failed: '" + DiagnosticInformation(ex, false) + "'." } }); /* Exception for actions. Normally we would handle this inside SendJsonError(). */ if (verbose) fail->Set("diagnostic_information", DiagnosticInformation(ex)); results.emplace_back(std::move(fail)); } } int statusCode = 500; for (const Dictionary::Ptr& res : results) { if (res->Contains("code") && res->Get("code") == 200) { statusCode = 200; break; } } response.result(statusCode); Dictionary::Ptr result = new Dictionary({ { "results", new Array(std::move(results)) } }); HttpUtility::SendJsonBody(response, params, result); return true; }