LLVM 23.0.0git
HTTPServer.cpp
Go to the documentation of this file.
1//===--- HTTPServer.cpp - HTTP server library -----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10///
11/// This file defines the methods of the HTTPServer class and the streamFile
12/// function.
13///
14//===----------------------------------------------------------------------===//
15
17
19#include "llvm/ADT/StringRef.h"
20#include "llvm/Support/Errc.h"
21#include "llvm/Support/Error.h"
24#include "llvm/Support/Regex.h"
25
26#ifdef LLVM_ENABLE_HTTPLIB
27#include "httplib.h"
28#endif
29
30using namespace llvm;
31
32char HTTPServerError::ID = 0;
33
34HTTPServerError::HTTPServerError(const Twine &Msg) : Msg(Msg.str()) {}
35
36void HTTPServerError::log(raw_ostream &OS) const { OS << Msg; }
37
40 if (Error Err = FDOrErr.takeError()) {
41 consumeError(std::move(Err));
42 Request.setResponse({404u, "text/plain", "Could not open file to read.\n"});
43 return false;
44 }
46 MemoryBuffer::getOpenFile(*FDOrErr, FilePath,
47 /*FileSize=*/-1,
48 /*RequiresNullTerminator=*/false);
49 sys::fs::closeFile(*FDOrErr);
50 if (Error Err = errorCodeToError(MBOrErr.getError())) {
51 consumeError(std::move(Err));
52 Request.setResponse({404u, "text/plain", "Could not memory-map file.\n"});
53 return false;
54 }
55 // Lambdas are copied on conversion to std::function, preventing use of
56 // smart pointers.
57 MemoryBuffer *MB = MBOrErr->release();
58 Request.setResponse({200u, "application/octet-stream", MB->getBufferSize(),
59 [=](size_t Offset, size_t Length) -> StringRef {
60 return MB->getBuffer().substr(Offset, Length);
61 },
62 [=](bool Success) { delete MB; }});
63 return true;
64}
65
66#ifdef LLVM_ENABLE_HTTPLIB
67
68bool HTTPServer::isAvailable() { return true; }
69
70HTTPServer::HTTPServer() { Server = std::make_unique<httplib::Server>(); }
71
73
74static void expandUrlPathMatches(const std::smatch &Matches,
75 HTTPServerRequest &Request) {
76 bool UrlPathSet = false;
77 for (const auto &it : Matches) {
78 if (UrlPathSet)
79 Request.UrlPathMatches.push_back(it);
80 else {
81 Request.UrlPath = it;
82 UrlPathSet = true;
83 }
84 }
85}
86
87HTTPServerRequest::HTTPServerRequest(const httplib::Request &HTTPLibRequest,
88 httplib::Response &HTTPLibResponse)
89 : HTTPLibResponse(HTTPLibResponse) {
90 expandUrlPathMatches(HTTPLibRequest.matches, *this);
91}
92
94 HTTPLibResponse.set_content(Response.Body.begin(), Response.Body.size(),
95 Response.ContentType);
96 HTTPLibResponse.status = Response.Code;
97}
98
100 HTTPLibResponse.set_content_provider(
101 Response.ContentLength, Response.ContentType,
102 [=](size_t Offset, size_t Length, httplib::DataSink &Sink) {
103 if (Offset < Response.ContentLength) {
104 StringRef Chunk = Response.Provider(Offset, Length);
105 Sink.write(Chunk.begin(), Chunk.size());
106 }
107 return true;
108 },
109 [=](bool Success) { Response.CompletionHandler(Success); });
110
111 HTTPLibResponse.status = Response.Code;
112}
113
114Error HTTPServer::get(StringRef UrlPathPattern, HTTPRequestHandler Handler) {
115 std::string ErrorMessage;
116 if (!Regex(UrlPathPattern).isValid(ErrorMessage))
118 Server->Get(std::string(UrlPathPattern),
119 [Handler](const httplib::Request &HTTPLibRequest,
120 httplib::Response &HTTPLibResponse) {
121 HTTPServerRequest Request(HTTPLibRequest, HTTPLibResponse);
122 Handler(Request);
123 });
124 return Error::success();
125}
126
127Error HTTPServer::bind(unsigned ListenPort, const char *HostInterface) {
128 if (!Server->bind_to_port(HostInterface, ListenPort))
130 "Could not assign requested address.");
131 Port = ListenPort;
132 return Error::success();
133}
134
135Expected<unsigned> HTTPServer::bind(const char *HostInterface) {
136 int ListenPort = Server->bind_to_any_port(HostInterface);
137 if (ListenPort < 0)
139 "Could not assign any port on requested address.");
140 return Port = ListenPort;
141}
142
144 if (!Port)
146 "Cannot listen without first binding to a port.");
147 if (!Server->listen_after_bind())
148 return createStringError(
150 "An unknown error occurred when cpp-httplib attempted to listen.");
151 return Error::success();
152}
153
154void HTTPServer::stop() {
155 Server->stop();
156 Port = 0;
157}
158
159#else
160
161// TODO: Implement barebones standalone HTTP server implementation.
162bool HTTPServer::isAvailable() { return false; }
163
164HTTPServer::HTTPServer() = default;
165
166HTTPServer::~HTTPServer() = default;
167
169 llvm_unreachable("no httplib");
170}
171
175
177 // TODO(https://github.com/llvm/llvm-project/issues/63873) We would ideally
178 // return an error as well but that's going to require refactoring of error
179 // handling in DebuginfodServer.
180 return Error::success();
181}
182
183Error HTTPServer::bind(unsigned ListenPort, const char *HostInterface) {
184 return make_error<HTTPServerError>("no httplib");
185}
186
187Expected<unsigned> HTTPServer::bind(const char *HostInterface) {
188 return make_error<HTTPServerError>("no httplib");
189}
190
192
193void HTTPServer::stop() { llvm_unreachable("no httplib"); }
194
195#endif // LLVM_ENABLE_HTTPLIB
This file contains the declarations of the HTTPServer and HTTPServerRequest classes,...
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
This file contains some functions that are useful when dealing with strings.
Represents either an error or a value T.
Definition ErrorOr.h:56
std::error_code getError() const
Definition ErrorOr.h:152
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
HTTPServerError(const Twine &Msg)
void log(raw_ostream &OS) const override
Print an error message to an output stream.
void setResponse(StreamingHTTPResponse Response)
SmallVector< std::string, 1 > UrlPathMatches
The elements correspond to match groups in the url path matching regex.
Definition HTTPServer.h:60
Error get(StringRef UrlPathPattern, HTTPRequestHandler Handler)
Registers a URL pattern routing rule.
Error bind(unsigned Port, const char *HostInterface="0.0.0.0")
Attempts to assign the requested port and interface, returning an Error upon failure.
Error listen()
Attempts to listen for requests on the bound port.
static bool isAvailable()
Returns true only if LLVM has been compiled with a working HTTPServer.
void stop()
If the server is listening, stop and unbind the socket.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
size_t getBufferSize() const
StringRef getBuffer() const
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:591
iterator begin() const
Definition StringRef.h:113
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:143
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI std::error_code closeFile(file_t &F)
Close the file object.
LLVM_ABI Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
@ Offset
Definition DWP.cpp:532
@ Length
Definition DWP.cpp:532
std::function< void(HTTPServerRequest &)> HTTPRequestHandler
Definition HTTPServer.h:74
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
@ argument_out_of_domain
Definition Errc.h:37
@ io_error
Definition Errc.h:58
@ Success
The lock was released successfully.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition Error.cpp:107
bool streamFile(HTTPServerRequest &Request, StringRef FilePath)
Sets the response to stream the file at FilePath, if available, and otherwise an HTTP 404 error respo...
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1083
const char * ContentType
Definition HTTPServer.h:70
Wraps the content provider with HTTP Status code and headers.
Definition HTTPServer.h:83
std::function< void(bool)> CompletionHandler
Called after the response transfer is complete with the success value of the transfer.
Definition HTTPServer.h:90