1 //===-- llvm/Debuginfod/HTTPServer.h - 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 /// This file contains the declarations of the HTTPServer and HTTPServerRequest 11 /// classes, the HTTPResponse, and StreamingHTTPResponse structs, and the 12 /// streamFile function. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_DEBUGINFOD_HTTPSERVER_H 17 #define LLVM_DEBUGINFOD_HTTPSERVER_H 18 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Support/Error.h" 21 22 #ifdef LLVM_ENABLE_HTTPLIB 23 // forward declarations 24 namespace httplib { 25 class Request; 26 class Response; 27 class Server; 28 } // namespace httplib 29 #endif 30 31 namespace llvm { 32 33 struct HTTPResponse; 34 struct StreamingHTTPResponse; 35 class HTTPServer; 36 37 class HTTPServerError : public ErrorInfo<HTTPServerError, ECError> { 38 public: 39 static char ID; 40 HTTPServerError(const Twine &Msg); 41 void log(raw_ostream &OS) const override; 42 43 private: 44 std::string Msg; 45 }; 46 47 class HTTPServerRequest { 48 friend HTTPServer; 49 50 #ifdef LLVM_ENABLE_HTTPLIB 51 private: 52 HTTPServerRequest(const httplib::Request &HTTPLibRequest, 53 httplib::Response &HTTPLibResponse); 54 httplib::Response &HTTPLibResponse; 55 #endif 56 57 public: 58 std::string UrlPath; 59 /// The elements correspond to match groups in the url path matching regex. 60 SmallVector<std::string, 1> UrlPathMatches; 61 62 // TODO bring in HTTP headers 63 64 void setResponse(StreamingHTTPResponse Response); 65 void setResponse(HTTPResponse Response); 66 }; 67 68 struct HTTPResponse { 69 unsigned Code; 70 const char *ContentType; 71 StringRef Body; 72 }; 73 74 typedef std::function<void(HTTPServerRequest &)> HTTPRequestHandler; 75 76 /// An HTTPContentProvider is called by the HTTPServer to obtain chunks of the 77 /// streaming response body. The returned chunk should be located at Offset 78 /// bytes and have Length bytes. 79 typedef std::function<StringRef(size_t /*Offset*/, size_t /*Length*/)> 80 HTTPContentProvider; 81 82 /// Wraps the content provider with HTTP Status code and headers. 83 struct StreamingHTTPResponse { 84 unsigned Code; 85 const char *ContentType; 86 size_t ContentLength; 87 HTTPContentProvider Provider; 88 /// Called after the response transfer is complete with the success value of 89 /// the transfer. 90 std::function<void(bool)> CompletionHandler = [](bool Success) {}; 91 }; 92 93 /// Sets the response to stream the file at FilePath, if available, and 94 /// otherwise an HTTP 404 error response. 95 bool streamFile(HTTPServerRequest &Request, StringRef FilePath); 96 97 /// An HTTP server which can listen on a single TCP/IP port for HTTP 98 /// requests and delgate them to the appropriate registered handler. 99 class HTTPServer { 100 #ifdef LLVM_ENABLE_HTTPLIB 101 std::unique_ptr<httplib::Server> Server; 102 unsigned Port = 0; 103 #endif 104 public: 105 HTTPServer(); 106 ~HTTPServer(); 107 108 /// Returns true only if LLVM has been compiled with a working HTTPServer. 109 static bool isAvailable(); 110 111 /// Registers a URL pattern routing rule. When the server is listening, each 112 /// request is dispatched to the first registered handler whose UrlPathPattern 113 /// matches the UrlPath. 114 Error get(StringRef UrlPathPattern, HTTPRequestHandler Handler); 115 116 /// Attempts to assign the requested port and interface, returning an Error 117 /// upon failure. 118 Error bind(unsigned Port, const char *HostInterface = "0.0.0.0"); 119 120 /// Attempts to assign any available port and interface, returning either the 121 /// port number or an Error upon failure. 122 Expected<unsigned> bind(const char *HostInterface = "0.0.0.0"); 123 124 /// Attempts to listen for requests on the bound port. Returns an Error if 125 /// called before binding a port. 126 Error listen(); 127 128 /// If the server is listening, stop and unbind the socket. 129 void stop(); 130 }; 131 } // end namespace llvm 132 133 #endif // LLVM_DEBUGINFOD_HTTPSERVER_H 134