LLVM 22.0.0git
HTTPClient.cpp
Go to the documentation of this file.
1//===-- llvm/Debuginfod/HTTPClient.cpp - HTTP client 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 defines the implementation of the HTTPClient library for issuing
11/// HTTP requests and handling the responses.
12///
13//===----------------------------------------------------------------------===//
14
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/Support/Errc.h"
19#include "llvm/Support/Error.h"
21#ifdef LLVM_ENABLE_CURL
22#include <curl/curl.h>
23#endif
24
25using namespace llvm;
26
28
29bool operator==(const HTTPRequest &A, const HTTPRequest &B) {
30 return A.Url == B.Url && A.Method == B.Method &&
31 A.FollowRedirects == B.FollowRedirects;
32}
33
35
36bool HTTPClient::IsInitialized = false;
37
43
44#ifdef LLVM_ENABLE_CURL
45
46bool HTTPClient::isAvailable() { return true; }
47
49 if (!IsInitialized) {
50 curl_global_init(CURL_GLOBAL_ALL);
51 IsInitialized = true;
52 }
53}
54
56 if (IsInitialized) {
57 curl_global_cleanup();
58 IsInitialized = false;
59 }
60}
61
62void HTTPClient::setTimeout(std::chrono::milliseconds Timeout) {
63 if (Timeout < std::chrono::milliseconds(0))
64 Timeout = std::chrono::milliseconds(0);
65 curl_easy_setopt(Curl, CURLOPT_TIMEOUT_MS, Timeout.count());
66}
67
68/// CurlHTTPRequest and the curl{Header,Write}Function are implementation
69/// details used to work with Curl. Curl makes callbacks with a single
70/// customizable pointer parameter.
71struct CurlHTTPRequest {
72 CurlHTTPRequest(HTTPResponseHandler &Handler) : Handler(Handler) {}
73 void storeError(Error Err) {
74 ErrorState = joinErrors(std::move(Err), std::move(ErrorState));
75 }
76 HTTPResponseHandler &Handler;
77 llvm::Error ErrorState = Error::success();
78};
79
80static size_t curlWriteFunction(char *Contents, size_t Size, size_t NMemb,
81 CurlHTTPRequest *CurlRequest) {
82 Size *= NMemb;
83 if (Error Err =
84 CurlRequest->Handler.handleBodyChunk(StringRef(Contents, Size))) {
85 CurlRequest->storeError(std::move(Err));
86 return 0;
87 }
88 return Size;
89}
90
93 "Must call HTTPClient::initialize() at the beginning of main().");
94 if (Curl)
95 return;
96 Curl = curl_easy_init();
97 assert(Curl && "Curl could not be initialized");
98 // Set the callback hooks.
99 curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, curlWriteFunction);
100 // Detect supported compressed encodings and accept all.
101 curl_easy_setopt(Curl, CURLOPT_ACCEPT_ENCODING, "");
102}
103
104HTTPClient::~HTTPClient() { curl_easy_cleanup(Curl); }
105
107 HTTPResponseHandler &Handler) {
108 if (Request.Method != HTTPMethod::GET)
110 "Unsupported CURL request method.");
111
112 SmallString<128> Url = Request.Url;
113 curl_easy_setopt(Curl, CURLOPT_URL, Url.c_str());
114 curl_easy_setopt(Curl, CURLOPT_FOLLOWLOCATION, Request.FollowRedirects);
115
116 curl_slist *Headers = nullptr;
117 for (const std::string &Header : Request.Headers)
118 Headers = curl_slist_append(Headers, Header.c_str());
119 curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, Headers);
120
121 CurlHTTPRequest CurlRequest(Handler);
122 curl_easy_setopt(Curl, CURLOPT_WRITEDATA, &CurlRequest);
123 CURLcode CurlRes = curl_easy_perform(Curl);
124 curl_slist_free_all(Headers);
125 if (CurlRes != CURLE_OK)
126 return joinErrors(std::move(CurlRequest.ErrorState),
128 "curl_easy_perform() failed: %s\n",
129 curl_easy_strerror(CurlRes)));
130 return std::move(CurlRequest.ErrorState);
131}
132
133unsigned HTTPClient::responseCode() {
134 long Code = 0;
135 curl_easy_getinfo(Curl, CURLINFO_RESPONSE_CODE, &Code);
136 return Code;
137}
138
139#else
140
141HTTPClient::HTTPClient() = default;
142
143HTTPClient::~HTTPClient() = default;
144
145bool HTTPClient::isAvailable() { return false; }
146
148
150
151void HTTPClient::setTimeout(std::chrono::milliseconds Timeout) {}
152
154 HTTPResponseHandler &Handler) {
155 llvm_unreachable("No HTTP Client implementation available.");
156}
157
159 llvm_unreachable("No HTTP Client implementation available.");
160}
161
162#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static const HTTPClientCleanup Cleanup
This file contains the declarations of the HTTPClient library for issuing HTTP requests and handling ...
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
static bool isAvailable()
Returns true only if LLVM has been compiled with a working HTTPClient.
static bool IsInitialized
Definition HTTPClient.h:62
unsigned responseCode()
Returns the last received response code or zero if none.
static void initialize()
Must be called at the beginning of a program, while it is a single thread.
Error perform(const HTTPRequest &Request, HTTPResponseHandler &Handler)
Performs the Request, passing response data to the Handler.
void setTimeout(std::chrono::milliseconds Timeout)
Sets the timeout for the entire request, in milliseconds.
static void cleanup()
Must be called at the end of a program, while it is a single thread.
A handler for state updates occurring while an HTTPRequest is performed.
Definition HTTPClient.h:43
const char * c_str()
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
NodeAddr< CodeNode * > Code
Definition RDFGraph.h:388
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1305
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
@ io_error
Definition Errc.h:58
@ invalid_argument
Definition Errc.h:56
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition Error.h:442
@ Timeout
Reached timeout while waiting for the owner to release the lock.
A stateless description of an outbound HTTP request.
Definition HTTPClient.h:30
SmallVector< std::string, 0 > Headers
Definition HTTPClient.h:32
HTTPRequest(StringRef Url)
SmallString< 128 > Url
Definition HTTPClient.h:31
HTTPMethod Method
Definition HTTPClient.h:33