1// Copyright 2015 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "buffet/http_transport_client.h"
16
17#include <base/bind.h>
18#include <brillo/errors/error.h>
19#include <brillo/http/http_request.h>
20#include <brillo/http/http_utils.h>
21#include <brillo/streams/memory_stream.h>
22#include <weave/enum_to_string.h>
23
24#include "buffet/weave_error_conversion.h"
25
26namespace buffet {
27
28namespace {
29
30using weave::provider::HttpClient;
31
32// The number of seconds each HTTP request will be allowed before timing out.
33const int kRequestTimeoutSeconds = 30;
34
35class ResponseImpl : public HttpClient::Response {
36 public:
37  ~ResponseImpl() override = default;
38  explicit ResponseImpl(std::unique_ptr<brillo::http::Response> response)
39      : response_{std::move(response)},
40        data_{response_->ExtractDataAsString()} {}
41
42  // HttpClient::Response implementation
43  int GetStatusCode() const override { return response_->GetStatusCode(); }
44
45  std::string GetContentType() const override {
46    return response_->GetContentType();
47  }
48
49  std::string GetData() const override { return data_; }
50
51 private:
52  std::unique_ptr<brillo::http::Response> response_;
53  std::string data_;
54  DISALLOW_COPY_AND_ASSIGN(ResponseImpl);
55};
56
57void OnSuccessCallback(const HttpClient::SendRequestCallback& callback,
58                       int id,
59                       std::unique_ptr<brillo::http::Response> response) {
60  callback.Run(std::unique_ptr<HttpClient::Response>{new ResponseImpl{
61                   std::move(response)}},
62               nullptr);
63}
64
65void OnErrorCallback(const HttpClient::SendRequestCallback& callback,
66                     int id,
67                     const brillo::Error* brillo_error) {
68  weave::ErrorPtr error;
69  ConvertError(*brillo_error, &error);
70  callback.Run(nullptr, std::move(error));
71}
72
73}  // anonymous namespace
74
75HttpTransportClient::HttpTransportClient()
76    : transport_{brillo::http::Transport::CreateDefault()} {
77  transport_->SetDefaultTimeout(
78      base::TimeDelta::FromSeconds(kRequestTimeoutSeconds));
79}
80
81HttpTransportClient::~HttpTransportClient() {}
82
83void HttpTransportClient::SendRequest(Method method,
84                                      const std::string& url,
85                                      const Headers& headers,
86                                      const std::string& data,
87                                      const SendRequestCallback& callback) {
88  brillo::http::Request request(url, weave::EnumToString(method), transport_);
89  request.AddHeaders(headers);
90  if (!data.empty()) {
91    auto stream = brillo::MemoryStream::OpenCopyOf(data, nullptr);
92    CHECK(stream->GetRemainingSize());
93    brillo::ErrorPtr cromeos_error;
94    if (!request.AddRequestBody(std::move(stream), &cromeos_error)) {
95      weave::ErrorPtr error;
96      ConvertError(*cromeos_error, &error);
97      transport_->RunCallbackAsync(
98          FROM_HERE, base::Bind(callback, nullptr, base::Passed(&error)));
99      return;
100    }
101  }
102  request.GetResponse(base::Bind(&OnSuccessCallback, callback),
103                      base::Bind(&OnErrorCallback, callback));
104}
105
106}  // namespace buffet
107