blob: 149d97924b6f3aac151565755243e5d7511d2a80 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// Copyright Epic Games, Inc. All Rights Reserved.
#include "frontend.h"
#include <zencore/endian.h>
#include <zencore/filesystem.h>
#include <zencore/string.h>
ZEN_THIRD_PARTY_INCLUDES_START
#if ZEN_PLATFORM_WINDOWS
# include <Windows.h>
#endif
ZEN_THIRD_PARTY_INCLUDES_END
namespace zen {
////////////////////////////////////////////////////////////////////////////////
HttpFrontendService::HttpFrontendService(std::filesystem::path Directory) : m_Directory(Directory)
{
std::filesystem::path SelfPath = GetRunningExecutablePath();
// Locate a .zip file appended onto the end of this binary
IoBuffer SelfBuffer = IoBufferBuilder::MakeFromFile(SelfPath);
m_ZipFs = ZipFs(std::move(SelfBuffer));
#if ZEN_BUILD_DEBUG
if (!Directory.empty())
{
return;
}
std::error_code ErrorCode;
auto Path = SelfPath;
while (Path.has_parent_path())
{
auto ParentPath = Path.parent_path();
if (ParentPath == Path)
{
break;
}
if (std::filesystem::is_regular_file(ParentPath / "xmake.lua", ErrorCode))
{
if (ErrorCode)
{
break;
}
auto HtmlDir = ParentPath / "zenserver" / "frontend" / "html";
if (std::filesystem::is_directory(HtmlDir, ErrorCode))
{
m_Directory = HtmlDir;
}
break;
}
Path = ParentPath;
};
#endif
}
////////////////////////////////////////////////////////////////////////////////
HttpFrontendService::~HttpFrontendService()
{
}
////////////////////////////////////////////////////////////////////////////////
const char*
HttpFrontendService::BaseUri() const
{
return "/dashboard"; // in order to use the root path we need to remove HttpAddUrlToUrlGroup in HttpSys.cpp
}
////////////////////////////////////////////////////////////////////////////////
void
HttpFrontendService::HandleRequest(zen::HttpServerRequest& Request)
{
using namespace std::literals;
std::string_view Uri = Request.RelativeUriWithExtension();
for (; Uri[0] == '/'; Uri = Uri.substr(1))
;
if (Uri.empty())
{
Uri = "index.html"sv;
}
// Dismiss if the URI contains .. anywhere to prevent arbitrary file reads
if (Uri.find("..") != Uri.npos)
{
return Request.WriteResponse(HttpResponseCode::Forbidden);
}
// Map the file extension to a MIME type. To keep things constrained, only a
// small subset of file extensions is allowed
HttpContentType ContentType = HttpContentType::kUnknownContentType;
if (const size_t DotIndex = Uri.rfind("."); DotIndex != Uri.npos)
{
const std::string_view DotExt = Uri.substr(DotIndex + 1);
ContentType = ParseContentType(DotExt);
}
if (ContentType == HttpContentType::kUnknownContentType)
{
return Request.WriteResponse(HttpResponseCode::Forbidden);
}
// The given content directory overrides any zip-fs discovered in the binary
if (!m_Directory.empty())
{
FileContents File = ReadFile(m_Directory / Uri);
if (!File.ErrorCode)
{
return Request.WriteResponse(HttpResponseCode::OK, ContentType, File.Data[0]);
}
}
if (IoBuffer FileBuffer = m_ZipFs.GetFile(Uri))
{
return Request.WriteResponse(HttpResponseCode::OK, ContentType, FileBuffer);
}
Request.WriteResponse(HttpResponseCode::NotFound, HttpContentType::kText, "Not found"sv);
}
} // namespace zen
|