LLVM 22.0.0git
HTTPServer.cpp
Go to the documentation of this file.
1//===-- llvm/Debuginfod/HTTPServer.cpp - HTTP server library -----*- C++-*-===//
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
18#include "llvm/ADT/StringRef.h"
19#include "llvm/Support/Errc.h"
20#include "llvm/Support/Error.h"
23#include "llvm/Support/Regex.h"
24
25#ifdef LLVM_ENABLE_HTTPLIB
26#include "httplib.h"
27#endif
28
29using namespace llvm;
30
31char HTTPServerError::ID = 0;
32
33HTTPServerError::HTTPServerError(const Twine &Msg) : Msg(Msg.str()) {}
34
35void HTTPServerError::log(raw_ostream &OS) const { OS << Msg; }
36
39 if (Error Err = FDOrErr.takeError()) {
40 consumeError(std::move(Err));
41 Request.setResponse({404u, "text/plain", "Could not open file to read.\n"});
42 return false;
43 }
45 MemoryBuffer::getOpenFile(*FDOrErr, FilePath,
46 /*FileSize=*/-1,
47 /*RequiresNullTerminator=*/false);
48 sys::fs::closeFile(*FDOrErr);
49 if (Error Err = errorCodeToError(MBOrErr.getError())) {
50 consumeError(std::move(Err));
51 Request.setResponse({404u, "text/plain", "Could not memory-map file.\n"});
52 return false;
53 }
54 // Lambdas are copied on conversion to std::function, preventing use of
55 // smart pointers.
56 MemoryBuffer *MB = MBOrErr->release();
57 Request.setResponse({200u, "application/octet-stream", MB->getBufferSize(),
58 [=](size_t Offset, size_t Length) -> StringRef {
59 return MB->getBuffer().substr(Offset, Length);
60 },
61 [=](bool Success) { delete MB; }});
62 return true;
63}
64
65#ifdef LLVM_ENABLE_HTTPLIB
66
67bool HTTPServer::isAvailable() { return true; }
68
69HTTPServer::HTTPServer() { Server = std::make_unique<httplib::Server>(); }
70
72
73static void expandUrlPathMatches(const std::smatch &Matches,
74 HTTPServerRequest &Request) {
75 bool UrlPathSet = false;
76 for (const auto &it : Matches) {
77 if (UrlPathSet)
78 Request.UrlPathMatches.push_back(it);
79 else {
80 Request.UrlPath = it;
81 UrlPathSet = true;
82 }
83 }
84}
85
86HTTPServerRequest::HTTPServerRequest(const httplib::Request &HTTPLibRequest,
87 httplib::Response &HTTPLibResponse)
88 : HTTPLibResponse(HTTPLibResponse) {
89 expandUrlPathMatches(HTTPLibRequest.matches, *this);
90}
91
93 HTTPLibResponse.set_content(Response.Body.begin(), Response.Body.size(),
94 Response.ContentType);
95 HTTPLibResponse.status = Response.Code;
96}
97
99 HTTPLibResponse.set_content_provider(
100 Response.ContentLength, Response.ContentType,
101 [=](size_t Offset, size_t Length, httplib::DataSink &Sink) {
102 if (Offset < Response.ContentLength) {
103 StringRef Chunk = Response.Provider(Offset, Length);
104 Sink.write(Chunk.begin(), Chunk.size());
105 }
106 return true;
107 },
108 [=](bool Success) { Response.CompletionHandler(Success); });
109
110 HTTPLibResponse.status = Response.Code;
111}
112
113Error HTTPServer::get(StringRef UrlPathPattern, HTTPRequestHandler Handler) {
114 std::string ErrorMessage;
115 if (!Regex(UrlPathPattern).isValid(ErrorMessage))
117 Server->Get(std::string(UrlPathPattern),
118 [Handler](const httplib::Request &HTTPLibRequest,
119 httplib::Response &HTTPLibResponse) {
120 HTTPServerRequest Request(HTTPLibRequest, HTTPLibResponse);
121 Handler(Request);
122 });
123 return Error::success();
124}
125
126Error HTTPServer::bind(unsigned ListenPort, const char *HostInterface) {
127 if (!Server->bind_to_port(HostInterface, ListenPort))
129 "Could not assign requested address.");
130 Port = ListenPort;
131 return Error::success();
132}
133
134Expected<unsigned> HTTPServer::bind(const char *HostInterface) {
135 int ListenPort = Server->bind_to_any_port(HostInterface);
136 if (ListenPort < 0)
138 "Could not assign any port on requested address.");
139 return Port = ListenPort;
140}
141
143 if (!Port)
145 "Cannot listen without first binding to a port.");
146 if (!Server->listen_after_bind())
147 return createStringError(
149 "An unknown error occurred when cpp-httplib attempted to listen.");
150 return Error::success();
151}
152
153void HTTPServer::stop() {
154 Server->stop();
155 Port = 0;
156}
157
158#else
159
160// TODO: Implement barebones standalone HTTP server implementation.
161bool HTTPServer::isAvailable() { return false; }
162
163HTTPServer::HTTPServer() = default;
164
165HTTPServer::~HTTPServer() = default;
166
168 llvm_unreachable("no httplib");
169}
170
174
176 // TODO(https://github.com/llvm/llvm-project/issues/63873) We would ideally
177 // return an error as well but that's going to require refactoring of error
178 // handling in DebuginfodServer.
179 return Error::success();
180}
181
182Error HTTPServer::bind(unsigned ListenPort, const char *HostInterface) {
183 return make_error<HTTPServerError>("no httplib");
184}
185
186Expected<unsigned> HTTPServer::bind(const char *HostInterface) {
187 return make_error<HTTPServerError>("no httplib");
188}
189
191 return make_error<HTTPServerError>("no httplib");
192}
193
195 llvm_unreachable("no httplib");
196}
197
198#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:581
iterator begin() const
Definition StringRef.h:120
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:154
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.
@ Offset
Definition DWP.cpp:477
@ Length
Definition DWP.cpp:477
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:111
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