1753f127fSDimitry Andric //===-- llvm/Debuginfod/HTTPServer.h - HTTP server library ------*- C++ -*-===// 2753f127fSDimitry Andric // 3753f127fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4753f127fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5753f127fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6753f127fSDimitry Andric // 7753f127fSDimitry Andric //===----------------------------------------------------------------------===// 8753f127fSDimitry Andric /// 9753f127fSDimitry Andric /// \file 10753f127fSDimitry Andric /// This file contains the declarations of the HTTPServer and HTTPServerRequest 11753f127fSDimitry Andric /// classes, the HTTPResponse, and StreamingHTTPResponse structs, and the 12753f127fSDimitry Andric /// streamFile function. 13753f127fSDimitry Andric /// 14753f127fSDimitry Andric //===----------------------------------------------------------------------===// 15753f127fSDimitry Andric 16fcaf7f86SDimitry Andric #ifndef LLVM_DEBUGINFOD_HTTPSERVER_H 17fcaf7f86SDimitry Andric #define LLVM_DEBUGINFOD_HTTPSERVER_H 18753f127fSDimitry Andric 19753f127fSDimitry Andric #include "llvm/ADT/StringRef.h" 20753f127fSDimitry Andric #include "llvm/Support/Error.h" 21753f127fSDimitry Andric 22753f127fSDimitry Andric #ifdef LLVM_ENABLE_HTTPLIB 23753f127fSDimitry Andric // forward declarations 24753f127fSDimitry Andric namespace httplib { 25753f127fSDimitry Andric class Request; 26753f127fSDimitry Andric class Response; 27753f127fSDimitry Andric class Server; 28753f127fSDimitry Andric } // namespace httplib 29753f127fSDimitry Andric #endif 30753f127fSDimitry Andric 31753f127fSDimitry Andric namespace llvm { 32753f127fSDimitry Andric 33753f127fSDimitry Andric struct HTTPResponse; 34753f127fSDimitry Andric struct StreamingHTTPResponse; 35753f127fSDimitry Andric class HTTPServer; 36753f127fSDimitry Andric 37*06c3fb27SDimitry Andric class HTTPServerError : public ErrorInfo<HTTPServerError, ECError> { 38*06c3fb27SDimitry Andric public: 39*06c3fb27SDimitry Andric static char ID; 40*06c3fb27SDimitry Andric HTTPServerError(const Twine &Msg); 41*06c3fb27SDimitry Andric void log(raw_ostream &OS) const override; 42*06c3fb27SDimitry Andric 43*06c3fb27SDimitry Andric private: 44*06c3fb27SDimitry Andric std::string Msg; 45*06c3fb27SDimitry Andric }; 46*06c3fb27SDimitry Andric 47753f127fSDimitry Andric class HTTPServerRequest { 48753f127fSDimitry Andric friend HTTPServer; 49753f127fSDimitry Andric 50753f127fSDimitry Andric #ifdef LLVM_ENABLE_HTTPLIB 51753f127fSDimitry Andric private: 52753f127fSDimitry Andric HTTPServerRequest(const httplib::Request &HTTPLibRequest, 53753f127fSDimitry Andric httplib::Response &HTTPLibResponse); 54753f127fSDimitry Andric httplib::Response &HTTPLibResponse; 55753f127fSDimitry Andric #endif 56753f127fSDimitry Andric 57753f127fSDimitry Andric public: 58753f127fSDimitry Andric std::string UrlPath; 59753f127fSDimitry Andric /// The elements correspond to match groups in the url path matching regex. 60753f127fSDimitry Andric SmallVector<std::string, 1> UrlPathMatches; 61753f127fSDimitry Andric 62753f127fSDimitry Andric // TODO bring in HTTP headers 63753f127fSDimitry Andric 64753f127fSDimitry Andric void setResponse(StreamingHTTPResponse Response); 65753f127fSDimitry Andric void setResponse(HTTPResponse Response); 66753f127fSDimitry Andric }; 67753f127fSDimitry Andric 68753f127fSDimitry Andric struct HTTPResponse { 69753f127fSDimitry Andric unsigned Code; 70753f127fSDimitry Andric const char *ContentType; 71753f127fSDimitry Andric StringRef Body; 72753f127fSDimitry Andric }; 73753f127fSDimitry Andric 74753f127fSDimitry Andric typedef std::function<void(HTTPServerRequest &)> HTTPRequestHandler; 75753f127fSDimitry Andric 76753f127fSDimitry Andric /// An HTTPContentProvider is called by the HTTPServer to obtain chunks of the 77753f127fSDimitry Andric /// streaming response body. The returned chunk should be located at Offset 78753f127fSDimitry Andric /// bytes and have Length bytes. 79753f127fSDimitry Andric typedef std::function<StringRef(size_t /*Offset*/, size_t /*Length*/)> 80753f127fSDimitry Andric HTTPContentProvider; 81753f127fSDimitry Andric 82753f127fSDimitry Andric /// Wraps the content provider with HTTP Status code and headers. 83753f127fSDimitry Andric struct StreamingHTTPResponse { 84753f127fSDimitry Andric unsigned Code; 85753f127fSDimitry Andric const char *ContentType; 86753f127fSDimitry Andric size_t ContentLength; 87753f127fSDimitry Andric HTTPContentProvider Provider; 88753f127fSDimitry Andric /// Called after the response transfer is complete with the success value of 89753f127fSDimitry Andric /// the transfer. 90753f127fSDimitry Andric std::function<void(bool)> CompletionHandler = [](bool Success) {}; 91753f127fSDimitry Andric }; 92753f127fSDimitry Andric 93753f127fSDimitry Andric /// Sets the response to stream the file at FilePath, if available, and 94753f127fSDimitry Andric /// otherwise an HTTP 404 error response. 95753f127fSDimitry Andric bool streamFile(HTTPServerRequest &Request, StringRef FilePath); 96753f127fSDimitry Andric 97753f127fSDimitry Andric /// An HTTP server which can listen on a single TCP/IP port for HTTP 98753f127fSDimitry Andric /// requests and delgate them to the appropriate registered handler. 99753f127fSDimitry Andric class HTTPServer { 100753f127fSDimitry Andric #ifdef LLVM_ENABLE_HTTPLIB 101753f127fSDimitry Andric std::unique_ptr<httplib::Server> Server; 102753f127fSDimitry Andric unsigned Port = 0; 103753f127fSDimitry Andric #endif 104753f127fSDimitry Andric public: 105753f127fSDimitry Andric HTTPServer(); 106753f127fSDimitry Andric ~HTTPServer(); 107753f127fSDimitry Andric 108753f127fSDimitry Andric /// Returns true only if LLVM has been compiled with a working HTTPServer. 109753f127fSDimitry Andric static bool isAvailable(); 110753f127fSDimitry Andric 111753f127fSDimitry Andric /// Registers a URL pattern routing rule. When the server is listening, each 112753f127fSDimitry Andric /// request is dispatched to the first registered handler whose UrlPathPattern 113753f127fSDimitry Andric /// matches the UrlPath. 114753f127fSDimitry Andric Error get(StringRef UrlPathPattern, HTTPRequestHandler Handler); 115753f127fSDimitry Andric 116753f127fSDimitry Andric /// Attempts to assign the requested port and interface, returning an Error 117753f127fSDimitry Andric /// upon failure. 118753f127fSDimitry Andric Error bind(unsigned Port, const char *HostInterface = "0.0.0.0"); 119753f127fSDimitry Andric 120753f127fSDimitry Andric /// Attempts to assign any available port and interface, returning either the 121753f127fSDimitry Andric /// port number or an Error upon failure. 122753f127fSDimitry Andric Expected<unsigned> bind(const char *HostInterface = "0.0.0.0"); 123753f127fSDimitry Andric 124753f127fSDimitry Andric /// Attempts to listen for requests on the bound port. Returns an Error if 125753f127fSDimitry Andric /// called before binding a port. 126753f127fSDimitry Andric Error listen(); 127753f127fSDimitry Andric 128753f127fSDimitry Andric /// If the server is listening, stop and unbind the socket. 129753f127fSDimitry Andric void stop(); 130753f127fSDimitry Andric }; 131753f127fSDimitry Andric } // end namespace llvm 132753f127fSDimitry Andric 133fcaf7f86SDimitry Andric #endif // LLVM_DEBUGINFOD_HTTPSERVER_H 134