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