LLVM  16.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 
17 #include "llvm/ADT/StringExtras.h"
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 
29 using namespace llvm;
30 
31 bool llvm::streamFile(HTTPServerRequest &Request, StringRef FilePath) {
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 
61 bool HTTPServer::isAvailable() { return true; }
62 
63 HTTPServer::HTTPServer() { Server = std::make_unique<httplib::Server>(); }
64 
66 
67 static 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 
80 HTTPServerRequest::HTTPServerRequest(const httplib::Request &HTTPLibRequest,
81  httplib::Response &HTTPLibResponse)
82  : HTTPLibResponse(HTTPLibResponse) {
83  expandUrlPathMatches(HTTPLibRequest.matches, *this);
84 }
85 
86 void HTTPServerRequest::setResponse(HTTPResponse Response) {
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 
107 Error HTTPServer::get(StringRef UrlPathPattern, HTTPRequestHandler Handler) {
108  std::string ErrorMessage;
109  if (!Regex(UrlPathPattern).isValid(ErrorMessage))
110  return createStringError(errc::argument_out_of_domain, 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 
120 Error 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 
128 Expected<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 
147 void HTTPServer::stop() {
148  Server->stop();
149  Port = 0;
150 }
151 
152 #else
153 
154 // TODO: Implement barebones standalone HTTP server implementation.
155 bool HTTPServer::isAvailable() { return false; }
156 
157 HTTPServer::HTTPServer() = default;
158 
159 HTTPServer::~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 
173 Error HTTPServer::bind(unsigned ListenPort, const char *HostInterface) {
174  llvm_unreachable("No HTTP server implementation available");
175 }
176 
177 Expected<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
MemoryBuffer.h
llvm::HTTPResponse::Code
unsigned Code
Definition: HTTPServer.h:59
llvm::HTTPResponse
Definition: HTTPServer.h:58
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
it
into xmm2 addss xmm2 xmm1 xmm3 addss xmm3 movaps xmm0 unpcklps xmm0 ret seems silly when it could just be one addps Expand libm rounding functions main should enable SSE DAZ mode and other fast SSE modes Think about doing i64 math in SSE regs on x86 This testcase should have no SSE instructions in it
Definition: README-SSE.txt:81
HTTPServer.h
FileSystem.h
StringRef.h
llvm::HTTPServerRequest::UrlPath
std::string UrlPath
Definition: HTTPServer.h:48
llvm::MemoryBuffer::getOpenFile
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, Optional< Align > Alignment=std::nullopt)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
Definition: MemoryBuffer.cpp:519
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
Error.h
llvm::HTTPServer::listen
Error listen()
Attempts to listen for requests on the bound port.
Definition: HTTPServer.cpp:181
Errc.h
llvm::HTTPServerRequest::UrlPathMatches
SmallVector< std::string, 1 > UrlPathMatches
The elements correspond to match groups in the url path matching regex.
Definition: HTTPServer.h:50
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::streamFile
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
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1042
llvm::MemoryBuffer
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:51
llvm::errc::argument_out_of_domain
@ argument_out_of_domain
llvm::StreamingHTTPResponse::ContentLength
size_t ContentLength
Definition: HTTPServer.h:76
llvm::HTTPServer::stop
void stop()
If the server is listening, stop and unbind the socket.
Definition: HTTPServer.cpp:185
llvm::HTTPResponse::ContentType
const char * ContentType
Definition: HTTPServer.h:60
llvm::MemoryBuffer::getBufferSize
size_t getBufferSize() const
Definition: MemoryBuffer.h:68
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
llvm::ErrorOr::getError
std::error_code getError() const
Definition: ErrorOr.h:153
llvm::HTTPServer::~HTTPServer
~HTTPServer()
llvm::HTTPServer::HTTPServer
HTTPServer()
llvm::sys::fs::openNativeFileForRead
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.
llvm::MemoryBuffer::getBuffer
StringRef getBuffer() const
Definition: MemoryBuffer.h:70
llvm::StreamingHTTPResponse::CompletionHandler
std::function< void(bool)> CompletionHandler
Called after the response transfer is complete with the success value of the transfer.
Definition: HTTPServer.h:80
llvm::HTTPServer::get
Error get(StringRef UrlPathPattern, HTTPRequestHandler Handler)
Registers a URL pattern routing rule.
Definition: HTTPServer.cpp:169
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
StringExtras.h
Regex.h
llvm::sys::fs::closeFile
std::error_code closeFile(file_t &F)
Close the file object.
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::StreamingHTTPResponse::Code
unsigned Code
Definition: HTTPServer.h:74
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::cl::Sink
@ Sink
Definition: CommandLine.h:168
llvm::HTTPServerRequest
Definition: HTTPServer.h:37
llvm::HTTPServer::bind
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
llvm::StringRef::size
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1238
get
Should compile to something r4 addze r3 instead we get
Definition: README.txt:24
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
Success
#define Success
Definition: AArch64Disassembler.cpp:295
llvm::errc::io_error
@ io_error
llvm::HTTPRequestHandler
std::function< void(HTTPServerRequest &)> HTTPRequestHandler
Definition: HTTPServer.h:64
llvm::StreamingHTTPResponse::ContentType
const char * ContentType
Definition: HTTPServer.h:75
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:596
isValid
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Definition: RustDemangle.cpp:184
llvm::HTTPServerRequest::setResponse
void setResponse(StreamingHTTPResponse Response)
Definition: HTTPServer.cpp:165
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
substr
static StringRef substr(StringRef Str, uint64_t Len)
Definition: SimplifyLibCalls.cpp:299
llvm::HTTPServer::isAvailable
static bool isAvailable()
Returns true only if LLVM has been compiled with a working HTTPServer.
Definition: HTTPServer.cpp:155
llvm::Regex
Definition: Regex.h:28
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:111
llvm::HTTPResponse::Body
StringRef Body
Definition: HTTPServer.h:61
llvm::StreamingHTTPResponse
Wraps the content provider with HTTP Status code and headers.
Definition: HTTPServer.h:73