// Copyright Epic Games, Inc. All Rights Reserved. #include "vfsservice.h" #include "vfsimpl.h" #include namespace zen { using namespace std::literals; #if ZEN_WITH_VFS ////////////////////////////////////////////////////////////////////////// bool GetContentAsCbObject(HttpServerRequest& HttpReq, CbObject& Cb) { IoBuffer Payload = HttpReq.ReadPayload(); HttpContentType PayloadContentType = HttpReq.RequestContentType(); switch (PayloadContentType) { case HttpContentType::kJSON: case HttpContentType::kUnknownContentType: case HttpContentType::kText: { std::string JsonText(reinterpret_cast(Payload.GetData()), Payload.GetSize()); Cb = LoadCompactBinaryFromJson(JsonText).AsObject(); if (!Cb) { HttpReq.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "Content format not supported, expected JSON format"); return false; } } break; case HttpContentType::kCbObject: Cb = LoadCompactBinaryObject(Payload); if (!Cb) { HttpReq.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "Content format not supported, expected compact binary format"); return false; } break; default: HttpReq.WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "Invalid request content type"); return false; } return true; } ////////////////////////////////////////////////////////////////////////// // // to test: // // echo {"method": "mount", "params": {"path": "d:\\VFS_ROOT"}} | curl.exe http://localhost:8558/vfs --data-binary @- // echo {"method": "unmount"} | curl.exe http://localhost:8558/vfs --data-binary @- VfsService::VfsService() { m_Impl = new Impl; m_Router.RegisterRoute( "info", [&](HttpRouterRequest& Request) { CbObjectWriter Cbo; Cbo << "running" << m_Impl->IsVfsRunning(); Cbo << "rootpath" << m_Impl->GetMountpointPath(); Request.ServerRequest().WriteResponse(HttpResponseCode::OK, Cbo.Save()); }, HttpVerb::kGet | HttpVerb::kHead); m_Router.RegisterRoute( "", [&](HttpRouterRequest& Req) { CbObject Payload; if (!GetContentAsCbObject(Req.ServerRequest(), Payload)) return; std::string_view RpcName = Payload["method"sv].AsString(); if (RpcName == "mount"sv) { CbObjectView Params = Payload["params"sv].AsObjectView(); std::string_view Mountpath = Params["path"sv].AsString(); if (Mountpath.empty()) { return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "no path specified"); } if (m_Impl->IsVfsRunning()) { return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "VFS already mounted"); } try { m_Impl->Mount(Mountpath); } catch (const std::exception& Ex) { return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, Ex.what()); } Req.ServerRequest().WriteResponse(HttpResponseCode::OK); } else if (RpcName == "unmount"sv) { if (!m_Impl->IsVfsRunning()) { return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "VFS not active"); } try { m_Impl->Unmount(); } catch (const std::exception& Ex) { return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, Ex.what()); } Req.ServerRequest().WriteResponse(HttpResponseCode::OK); } else { Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, "unknown RPC"sv); } }, HttpVerb::kPost); } VfsService::~VfsService() { delete m_Impl; } void VfsService::Mount(std::string_view MountPoint) { m_Impl->Mount(MountPoint); } void VfsService::Unmount() { m_Impl->Unmount(); } void VfsService::AddService(Ref&& Ps) { m_Impl->AddService(std::move(Ps)); } void VfsService::AddService(Ref&& Z$) { m_Impl->AddService(std::move(Z$)); } #else VfsService::VfsService() { } VfsService::~VfsService() { } void VfsService::Mount(std::string_view MountPoint) { ZEN_UNUSED(MountPoint); } void VfsService::Unmount() { } void VfsService::AddService(Ref&& Ps) { ZEN_UNUSED(Ps); } void VfsService::AddService(Ref&& Z$) { ZEN_UNUSED(Z$); } #endif const char* VfsService::BaseUri() const { return "/vfs/"; } void VfsService::HandleRequest(HttpServerRequest& HttpServiceRequest) { m_Router.HandleRequest(HttpServiceRequest); } } // namespace zen