LLVM 17.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
33 if (Error Err = FDOrErr.takeError()) {
34 consumeError(std::move(Err));
35 Request.setResponse({404u, "text/plain", "Could not open file to read.\n"});
36 return false;
37 }
39 MemoryBuffer::getOpenFile(*FDOrErr, FilePath,
40 /*FileSize=*/-1,
41 /*RequiresNullTerminator=*/false);
42 sys::fs::closeFile(*FDOrErr);
43 if (Error Err = errorCodeToError(MBOrErr.getError())) {
44 consumeError(std::move(Err));
45 Request.setResponse({404u, "text/plain", "Could not memory-map file.\n"});
46 return false;
47 }
48 // Lambdas are copied on conversion to to std::function, preventing use of
49 // smart pointers.
50 MemoryBuffer *MB = MBOrErr->release();
51 Request.setResponse({200u, "application/octet-stream", MB->getBufferSize(),
52 [=](size_t Offset, size_t Length) -> StringRef {
53 return MB->getBuffer().substr(Offset, Length);
54 },
55 [=](bool Success) { delete MB; }});
56 return true;
57}
58
59#ifdef LLVM_ENABLE_HTTPLIB
60
61bool HTTPServer::isAvailable() { return true; }
62
63HTTPServer::HTTPServer() { Server = std::make_unique<httplib::Server>(); }
64
66
67static void expandUrlPathMatches(const std::smatch &Matches,
68 HTTPServerRequest &Request) {
69 bool UrlPathSet = false;
70 for (const auto &it : Matches) {
71 if (UrlPathSet)
72 Request.UrlPathMatches.push_back(it);
73 else {
74 Request.UrlPath = it;
75 UrlPathSet = true;
76 }
77 }
78}
79
80HTTPServerRequest::HTTPServerRequest(const httplib::Request &HTTPLibRequest,
81 httplib::Response &HTTPLibResponse)
82 : HTTPLibResponse(HTTPLibResponse) {
83 expandUrlPathMatches(HTTPLibRequest.matches, *this);
84}
85
87 HTTPLibResponse.set_content(Response.Body.begin(), Response.Body.size(),
88 Response.ContentType);
89 HTTPLibResponse.status = Response.Code;
90}
91
93 HTTPLibResponse.set_content_provider(
94 Response.ContentLength, Response.ContentType,
95 [=](size_t Offset, size_t Length, httplib::DataSink &Sink) {
96 if (Offset < Response.ContentLength) {
97 StringRef Chunk = Response.Provider(Offset, Length);
98 Sink.write(Chunk.begin(), Chunk.size());
99 }
100 return true;
101 },
102 [=](bool Success) { Response.CompletionHandler(Success); });
103
104 HTTPLibResponse.status = Response.Code;
105}
106
107Error HTTPServer::get(StringRef UrlPathPattern, HTTPRequestHandler Handler) {
108 std::string ErrorMessage;
109 if (!Regex(UrlPathPattern).isValid(ErrorMessage))
111 Server->Get(std::string(UrlPathPattern),
112 [Handler](const httplib::Request &HTTPLibRequest,
113 httplib::Response &HTTPLibResponse) {
114 HTTPServerRequest Request(HTTPLibRequest, HTTPLibResponse);
115 Handler(Request);
116 });
117 return Error::success();
118}
119
120Error HTTPServer::bind(unsigned ListenPort, const char *HostInterface) {
121 if (!Server->bind_to_port(HostInterface, ListenPort))
123 "Could not assign requested address.");
124 Port = ListenPort;
125 return Error::success();
126}
127
128Expected<unsigned> HTTPServer::bind(const char *HostInterface) {
129 int ListenPort = Server->bind_to_any_port(HostInterface);
130 if (ListenPort < 0)
132 "Could not assign any port on requested address.");
133 return Port = ListenPort;
134}
135
137 if (!Port)
139 "Cannot listen without first binding to a port.");
140 if (!Server->listen_after_bind())
141 return createStringError(
143 "An unknown error occurred when cpp-httplib attempted to listen.");
144 return Error::success();
145}
146
147void HTTPServer::stop() {
148 Server->stop();
149 Port = 0;
150}
151
152#else
153
154// TODO: Implement barebones standalone HTTP server implementation.
155bool HTTPServer::isAvailable() { return false; }
156
157HTTPServer::HTTPServer() = default;
158
159HTTPServer::~HTTPServer() = default;
160
162 llvm_unreachable("No HTTP server implementation available");
163}
164
166 llvm_unreachable("No HTTP server implementation available");
167}
168
170 llvm_unreachable("No HTTP server implementation available");
171}
172
173Error HTTPServer::bind(unsigned ListenPort, const char *HostInterface) {
174 llvm_unreachable("No HTTP server implementation available");
175}
176
177Expected<unsigned> HTTPServer::bind(const char *HostInterface) {
178 llvm_unreachable("No HTTP server implementation available");
179}
180
182 llvm_unreachable("No HTTP server implementation available");
183}
184
186 llvm_unreachable("No HTTP server implementation available");
187}
188
189#endif // LLVM_ENABLE_HTTPLIB
#define Success
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_>.
static StringRef substr(StringRef Str, uint64_t Len)
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:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Tagged union holding either a T or a Error.
Definition: Error.h:470
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
void setResponse(StreamingHTTPResponse Response)
Definition: HTTPServer.cpp:165
SmallVector< std::string, 1 > UrlPathMatches
The elements correspond to match groups in the url path matching regex.
Definition: HTTPServer.h:50
Error get(StringRef UrlPathPattern, HTTPRequestHandler Handler)
Registers a URL pattern routing rule.
Definition: HTTPServer.cpp:169
Error bind(unsigned Port, const char *HostInterface="0.0.0.0")
Attempts to assign the requested port and interface, returning an Error upon failure.
Definition: HTTPServer.cpp:173
Error listen()
Attempts to listen for requests on the bound port.
Definition: HTTPServer.cpp:181
static bool isAvailable()
Returns true only if LLVM has been compiled with a working HTTPServer.
Definition: HTTPServer.cpp:155
void stop()
If the server is listening, stop and unbind the socket.
Definition: HTTPServer.cpp:185
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
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
Definition: MemoryBuffer.h:68
StringRef getBuffer() const
Definition: MemoryBuffer.h:70
void push_back(const T &Elt)
Definition: SmallVector.h:416
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
iterator begin() const
Definition: StringRef.h:111
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::error_code closeFile(file_t &F)
Close the file object.
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: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
@ Length
Definition: DWP.cpp:440
std::function< void(HTTPServerRequest &)> HTTPRequestHandler
Definition: HTTPServer.h:64
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
@ argument_out_of_domain
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
bool streamFile(HTTPServerRequest &Request, StringRef FilePath)
Sets the response to stream the file at FilePath, if available, and otherwise an HTTP 404 error respo...
Definition: HTTPServer.cpp:31
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
const char * ContentType
Definition: HTTPServer.h:60
StringRef Body
Definition: HTTPServer.h:61
Wraps the content provider with HTTP Status code and headers.
Definition: HTTPServer.h:73
std::function< void(bool)> CompletionHandler
Called after the response transfer is complete with the success value of the transfer.
Definition: HTTPServer.h:80