blob: eec4a98aefc5cecb9bf52813caaf80d07e0458a8 [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_HTTP_REQUEST_H_
#define SHILL_HTTP_REQUEST_H_
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <vector>
#include <base/cancelable_callback.h>
#include <base/functional/callback.h>
#include <base/memory/ref_counted.h>
#include <base/memory/weak_ptr.h>
#include <base/types/expected.h>
#include <brillo/errors/error.h>
#include <brillo/http/http_transport.h>
#include <net-base/http_url.h>
#include <net-base/ip_address.h>
#include "shill/dns_client.h"
namespace shill {
class Error;
class EventDispatcher;
// The HttpRequest class implements facilities for performing a simple "GET"
// request and returning the contents via a callback. By default, this class
// will only be allowed to communicate with Google servers when secure (HTTPS)
// communication is used.
class HttpRequest {
public:
// Represents possible errors for an HTTP requests.
enum class Error {
// Internal error: unknown error, incorrect request id, error code
// conversion error, ...
kInternalError,
// Name resolution failed.
kDNSFailure,
// Name resolution timed out.
kDNSTimeout,
// The HTTP connection failed.
kConnectionFailure,
// The TLS connection failed.
kTLSFailure,
// The HTTP network IO failed.
kIOError,
// The HTTP request timed out.
kHTTPTimeout,
};
static std::string_view ErrorName(Error error);
// |allow_non_google_https| determines whether or not secure (HTTPS)
// communication with a non-Google server is allowed. Note that this
// will not change any behavior for HTTP communication.
HttpRequest(EventDispatcher* dispatcher,
const std::string& interface_name,
net_base::IPFamily ip_family,
const std::vector<net_base::IPAddress>& dns_list,
bool allow_non_google_https = false,
std::shared_ptr<brillo::http::Transport> transport =
brillo::http::Transport::CreateDefault());
HttpRequest(const HttpRequest&) = delete;
HttpRequest& operator=(const HttpRequest&) = delete;
virtual ~HttpRequest();
// Start an http GET request to the URL |url|. If the request succeeds,
// std::nullopt is returned and |request_success_callback| is called
// asynchronously with the response data. Otherwise, if the request fails to
// start an error is returned immediately or |request_error_callback| is
// called with the error reason.
virtual std::optional<Error> Start(
const std::string& logging_tag,
const net_base::HttpUrl& url,
const brillo::http::HeaderList& headers,
base::OnceCallback<void(std::shared_ptr<brillo::http::Response>)>
request_success_callback,
base::OnceCallback<void(Error)> request_error_callback);
// Stop the current HttpRequest. No callback is called as a side
// effect of this function.
virtual void Stop();
virtual const std::string& logging_tag() const { return logging_tag_; }
private:
friend class HttpRequestTest;
// Time to wait for HTTP request.
static constexpr base::TimeDelta kRequestTimeout = base::Seconds(10);
void GetDNSResult(
const base::expected<net_base::IPAddress, shill::Error>& address);
void StartRequest();
void SuccessCallback(brillo::http::RequestID request_id,
std::unique_ptr<brillo::http::Response> response);
void ErrorCallback(brillo::http::RequestID request_id,
const brillo::Error* error);
void SendError(Error error);
std::string logging_tag_;
net_base::IPFamily ip_family_;
std::vector<net_base::IPAddress> dns_list_;
base::WeakPtrFactory<HttpRequest> weak_ptr_factory_;
DnsClient::ClientCallback dns_client_callback_;
base::OnceCallback<void(Error)> request_error_callback_;
base::OnceCallback<void(std::shared_ptr<brillo::http::Response>)>
request_success_callback_;
std::unique_ptr<DnsClient> dns_client_;
std::shared_ptr<brillo::http::Transport> transport_;
brillo::http::RequestID request_id_;
net_base::HttpUrl url_;
brillo::http::HeaderList headers_;
bool is_running_;
};
std::ostream& operator<<(std::ostream& stream, HttpRequest::Error error);
std::ostream& operator<<(std::ostream& stream,
std::optional<HttpRequest::Error> error);
} // namespace shill
#endif // SHILL_HTTP_REQUEST_H_