xref: /aosp_15_r20/external/libbrillo/brillo/http/http_utils.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright 2014 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #include <brillo/http/http_utils.h>
6*1a96fba6SXin Li 
7*1a96fba6SXin Li #include <algorithm>
8*1a96fba6SXin Li 
9*1a96fba6SXin Li #include <base/bind.h>
10*1a96fba6SXin Li #include <base/json/json_reader.h>
11*1a96fba6SXin Li #include <base/json/json_writer.h>
12*1a96fba6SXin Li #include <base/values.h>
13*1a96fba6SXin Li #include <brillo/data_encoding.h>
14*1a96fba6SXin Li #include <brillo/errors/error_codes.h>
15*1a96fba6SXin Li #include <brillo/mime_utils.h>
16*1a96fba6SXin Li #include <brillo/streams/memory_stream.h>
17*1a96fba6SXin Li 
18*1a96fba6SXin Li using brillo::mime::AppendParameter;
19*1a96fba6SXin Li using brillo::mime::RemoveParameters;
20*1a96fba6SXin Li 
21*1a96fba6SXin Li namespace brillo {
22*1a96fba6SXin Li namespace http {
23*1a96fba6SXin Li 
GetAndBlock(const std::string & url,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)24*1a96fba6SXin Li std::unique_ptr<Response> GetAndBlock(const std::string& url,
25*1a96fba6SXin Li                                       const HeaderList& headers,
26*1a96fba6SXin Li                                       std::shared_ptr<Transport> transport,
27*1a96fba6SXin Li                                       brillo::ErrorPtr* error) {
28*1a96fba6SXin Li   return SendRequestWithNoDataAndBlock(
29*1a96fba6SXin Li       request_type::kGet, url, headers, transport, error);
30*1a96fba6SXin Li }
31*1a96fba6SXin Li 
Get(const std::string & url,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)32*1a96fba6SXin Li RequestID Get(const std::string& url,
33*1a96fba6SXin Li               const HeaderList& headers,
34*1a96fba6SXin Li               std::shared_ptr<Transport> transport,
35*1a96fba6SXin Li               const SuccessCallback& success_callback,
36*1a96fba6SXin Li               const ErrorCallback& error_callback) {
37*1a96fba6SXin Li   return SendRequestWithNoData(request_type::kGet,
38*1a96fba6SXin Li                                url,
39*1a96fba6SXin Li                                headers,
40*1a96fba6SXin Li                                transport,
41*1a96fba6SXin Li                                success_callback,
42*1a96fba6SXin Li                                error_callback);
43*1a96fba6SXin Li }
44*1a96fba6SXin Li 
HeadAndBlock(const std::string & url,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)45*1a96fba6SXin Li std::unique_ptr<Response> HeadAndBlock(const std::string& url,
46*1a96fba6SXin Li                                        std::shared_ptr<Transport> transport,
47*1a96fba6SXin Li                                        brillo::ErrorPtr* error) {
48*1a96fba6SXin Li   return SendRequestWithNoDataAndBlock(
49*1a96fba6SXin Li       request_type::kHead, url, {}, transport, error);
50*1a96fba6SXin Li }
51*1a96fba6SXin Li 
Head(const std::string & url,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)52*1a96fba6SXin Li RequestID Head(const std::string& url,
53*1a96fba6SXin Li                std::shared_ptr<Transport> transport,
54*1a96fba6SXin Li                const SuccessCallback& success_callback,
55*1a96fba6SXin Li                const ErrorCallback& error_callback) {
56*1a96fba6SXin Li   return SendRequestWithNoData(request_type::kHead,
57*1a96fba6SXin Li                                url,
58*1a96fba6SXin Li                                {},
59*1a96fba6SXin Li                                transport,
60*1a96fba6SXin Li                                success_callback,
61*1a96fba6SXin Li                                error_callback);
62*1a96fba6SXin Li }
63*1a96fba6SXin Li 
PostTextAndBlock(const std::string & url,const std::string & data,const std::string & mime_type,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)64*1a96fba6SXin Li std::unique_ptr<Response> PostTextAndBlock(const std::string& url,
65*1a96fba6SXin Li                                            const std::string& data,
66*1a96fba6SXin Li                                            const std::string& mime_type,
67*1a96fba6SXin Li                                            const HeaderList& headers,
68*1a96fba6SXin Li                                            std::shared_ptr<Transport> transport,
69*1a96fba6SXin Li                                            brillo::ErrorPtr* error) {
70*1a96fba6SXin Li   return PostBinaryAndBlock(
71*1a96fba6SXin Li       url, data.data(), data.size(), mime_type, headers, transport, error);
72*1a96fba6SXin Li }
73*1a96fba6SXin Li 
PostText(const std::string & url,const std::string & data,const std::string & mime_type,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)74*1a96fba6SXin Li RequestID PostText(const std::string& url,
75*1a96fba6SXin Li                    const std::string& data,
76*1a96fba6SXin Li                    const std::string& mime_type,
77*1a96fba6SXin Li                    const HeaderList& headers,
78*1a96fba6SXin Li                    std::shared_ptr<Transport> transport,
79*1a96fba6SXin Li                    const SuccessCallback& success_callback,
80*1a96fba6SXin Li                    const ErrorCallback& error_callback) {
81*1a96fba6SXin Li   return PostBinary(url,
82*1a96fba6SXin Li                     data.data(),
83*1a96fba6SXin Li                     data.size(),
84*1a96fba6SXin Li                     mime_type,
85*1a96fba6SXin Li                     headers,
86*1a96fba6SXin Li                     transport,
87*1a96fba6SXin Li                     success_callback,
88*1a96fba6SXin Li                     error_callback);
89*1a96fba6SXin Li }
90*1a96fba6SXin Li 
SendRequestAndBlock(const std::string & method,const std::string & url,const void * data,size_t data_size,const std::string & mime_type,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)91*1a96fba6SXin Li std::unique_ptr<Response> SendRequestAndBlock(
92*1a96fba6SXin Li     const std::string& method,
93*1a96fba6SXin Li     const std::string& url,
94*1a96fba6SXin Li     const void* data,
95*1a96fba6SXin Li     size_t data_size,
96*1a96fba6SXin Li     const std::string& mime_type,
97*1a96fba6SXin Li     const HeaderList& headers,
98*1a96fba6SXin Li     std::shared_ptr<Transport> transport,
99*1a96fba6SXin Li     brillo::ErrorPtr* error) {
100*1a96fba6SXin Li   Request request(url, method, transport);
101*1a96fba6SXin Li   request.AddHeaders(headers);
102*1a96fba6SXin Li   if (data_size > 0) {
103*1a96fba6SXin Li     CHECK(!mime_type.empty()) << "MIME type must be specified if request body "
104*1a96fba6SXin Li                                  "message is provided";
105*1a96fba6SXin Li     request.SetContentType(mime_type);
106*1a96fba6SXin Li     if (!request.AddRequestBody(data, data_size, error))
107*1a96fba6SXin Li       return std::unique_ptr<Response>();
108*1a96fba6SXin Li   }
109*1a96fba6SXin Li   return request.GetResponseAndBlock(error);
110*1a96fba6SXin Li }
111*1a96fba6SXin Li 
SendRequestWithNoDataAndBlock(const std::string & method,const std::string & url,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)112*1a96fba6SXin Li std::unique_ptr<Response> SendRequestWithNoDataAndBlock(
113*1a96fba6SXin Li     const std::string& method,
114*1a96fba6SXin Li     const std::string& url,
115*1a96fba6SXin Li     const HeaderList& headers,
116*1a96fba6SXin Li     std::shared_ptr<Transport> transport,
117*1a96fba6SXin Li     brillo::ErrorPtr* error) {
118*1a96fba6SXin Li   return SendRequestAndBlock(
119*1a96fba6SXin Li       method, url, nullptr, 0, {}, headers, transport, error);
120*1a96fba6SXin Li }
121*1a96fba6SXin Li 
SendRequest(const std::string & method,const std::string & url,StreamPtr stream,const std::string & mime_type,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)122*1a96fba6SXin Li RequestID SendRequest(const std::string& method,
123*1a96fba6SXin Li                       const std::string& url,
124*1a96fba6SXin Li                       StreamPtr stream,
125*1a96fba6SXin Li                       const std::string& mime_type,
126*1a96fba6SXin Li                       const HeaderList& headers,
127*1a96fba6SXin Li                       std::shared_ptr<Transport> transport,
128*1a96fba6SXin Li                       const SuccessCallback& success_callback,
129*1a96fba6SXin Li                       const ErrorCallback& error_callback) {
130*1a96fba6SXin Li   Request request(url, method, transport);
131*1a96fba6SXin Li   request.AddHeaders(headers);
132*1a96fba6SXin Li   if (stream && (!stream->CanGetSize() || stream->GetRemainingSize() > 0)) {
133*1a96fba6SXin Li     CHECK(!mime_type.empty()) << "MIME type must be specified if request body "
134*1a96fba6SXin Li                                  "message is provided";
135*1a96fba6SXin Li     request.SetContentType(mime_type);
136*1a96fba6SXin Li     brillo::ErrorPtr error;
137*1a96fba6SXin Li     if (!request.AddRequestBody(std::move(stream), &error)) {
138*1a96fba6SXin Li       transport->RunCallbackAsync(
139*1a96fba6SXin Li           FROM_HERE, base::Bind(error_callback,
140*1a96fba6SXin Li                                 0, base::Owned(error.release())));
141*1a96fba6SXin Li       return 0;
142*1a96fba6SXin Li     }
143*1a96fba6SXin Li   }
144*1a96fba6SXin Li   return request.GetResponse(success_callback, error_callback);
145*1a96fba6SXin Li }
146*1a96fba6SXin Li 
SendRequest(const std::string & method,const std::string & url,const void * data,size_t data_size,const std::string & mime_type,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)147*1a96fba6SXin Li RequestID SendRequest(const std::string& method,
148*1a96fba6SXin Li                       const std::string& url,
149*1a96fba6SXin Li                       const void* data,
150*1a96fba6SXin Li                       size_t data_size,
151*1a96fba6SXin Li                       const std::string& mime_type,
152*1a96fba6SXin Li                       const HeaderList& headers,
153*1a96fba6SXin Li                       std::shared_ptr<Transport> transport,
154*1a96fba6SXin Li                       const SuccessCallback& success_callback,
155*1a96fba6SXin Li                       const ErrorCallback& error_callback) {
156*1a96fba6SXin Li   return SendRequest(method,
157*1a96fba6SXin Li                      url,
158*1a96fba6SXin Li                      MemoryStream::OpenCopyOf(data, data_size, nullptr),
159*1a96fba6SXin Li                      mime_type,
160*1a96fba6SXin Li                      headers,
161*1a96fba6SXin Li                      transport,
162*1a96fba6SXin Li                      success_callback,
163*1a96fba6SXin Li                      error_callback);
164*1a96fba6SXin Li }
165*1a96fba6SXin Li 
SendRequestWithNoData(const std::string & method,const std::string & url,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)166*1a96fba6SXin Li RequestID SendRequestWithNoData(const std::string& method,
167*1a96fba6SXin Li                                 const std::string& url,
168*1a96fba6SXin Li                                 const HeaderList& headers,
169*1a96fba6SXin Li                                 std::shared_ptr<Transport> transport,
170*1a96fba6SXin Li                                 const SuccessCallback& success_callback,
171*1a96fba6SXin Li                                 const ErrorCallback& error_callback) {
172*1a96fba6SXin Li   return SendRequest(method,
173*1a96fba6SXin Li                      url,
174*1a96fba6SXin Li                      {},
175*1a96fba6SXin Li                      {},
176*1a96fba6SXin Li                      headers,
177*1a96fba6SXin Li                      transport,
178*1a96fba6SXin Li                      success_callback,
179*1a96fba6SXin Li                      error_callback);
180*1a96fba6SXin Li }
181*1a96fba6SXin Li 
PostBinaryAndBlock(const std::string & url,const void * data,size_t data_size,const std::string & mime_type,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)182*1a96fba6SXin Li std::unique_ptr<Response> PostBinaryAndBlock(
183*1a96fba6SXin Li     const std::string& url,
184*1a96fba6SXin Li     const void* data,
185*1a96fba6SXin Li     size_t data_size,
186*1a96fba6SXin Li     const std::string& mime_type,
187*1a96fba6SXin Li     const HeaderList& headers,
188*1a96fba6SXin Li     std::shared_ptr<Transport> transport,
189*1a96fba6SXin Li     brillo::ErrorPtr* error) {
190*1a96fba6SXin Li   return SendRequestAndBlock(request_type::kPost,
191*1a96fba6SXin Li                              url,
192*1a96fba6SXin Li                              data,
193*1a96fba6SXin Li                              data_size,
194*1a96fba6SXin Li                              mime_type,
195*1a96fba6SXin Li                              headers,
196*1a96fba6SXin Li                              transport,
197*1a96fba6SXin Li                              error);
198*1a96fba6SXin Li }
199*1a96fba6SXin Li 
PostBinary(const std::string & url,StreamPtr stream,const std::string & mime_type,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)200*1a96fba6SXin Li RequestID PostBinary(const std::string& url,
201*1a96fba6SXin Li                      StreamPtr stream,
202*1a96fba6SXin Li                      const std::string& mime_type,
203*1a96fba6SXin Li                      const HeaderList& headers,
204*1a96fba6SXin Li                      std::shared_ptr<Transport> transport,
205*1a96fba6SXin Li                      const SuccessCallback& success_callback,
206*1a96fba6SXin Li                      const ErrorCallback& error_callback) {
207*1a96fba6SXin Li   return SendRequest(request_type::kPost,
208*1a96fba6SXin Li                      url,
209*1a96fba6SXin Li                      std::move(stream),
210*1a96fba6SXin Li                      mime_type,
211*1a96fba6SXin Li                      headers,
212*1a96fba6SXin Li                      transport,
213*1a96fba6SXin Li                      success_callback,
214*1a96fba6SXin Li                      error_callback);
215*1a96fba6SXin Li }
216*1a96fba6SXin Li 
PostBinary(const std::string & url,const void * data,size_t data_size,const std::string & mime_type,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)217*1a96fba6SXin Li RequestID PostBinary(const std::string& url,
218*1a96fba6SXin Li                      const void* data,
219*1a96fba6SXin Li                      size_t data_size,
220*1a96fba6SXin Li                      const std::string& mime_type,
221*1a96fba6SXin Li                      const HeaderList& headers,
222*1a96fba6SXin Li                      std::shared_ptr<Transport> transport,
223*1a96fba6SXin Li                      const SuccessCallback& success_callback,
224*1a96fba6SXin Li                      const ErrorCallback& error_callback) {
225*1a96fba6SXin Li   return SendRequest(request_type::kPost,
226*1a96fba6SXin Li                      url,
227*1a96fba6SXin Li                      data,
228*1a96fba6SXin Li                      data_size,
229*1a96fba6SXin Li                      mime_type,
230*1a96fba6SXin Li                      headers,
231*1a96fba6SXin Li                      transport,
232*1a96fba6SXin Li                      success_callback,
233*1a96fba6SXin Li                      error_callback);
234*1a96fba6SXin Li }
235*1a96fba6SXin Li 
PostFormDataAndBlock(const std::string & url,const FormFieldList & data,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)236*1a96fba6SXin Li std::unique_ptr<Response> PostFormDataAndBlock(
237*1a96fba6SXin Li     const std::string& url,
238*1a96fba6SXin Li     const FormFieldList& data,
239*1a96fba6SXin Li     const HeaderList& headers,
240*1a96fba6SXin Li     std::shared_ptr<Transport> transport,
241*1a96fba6SXin Li     brillo::ErrorPtr* error) {
242*1a96fba6SXin Li   std::string encoded_data = brillo::data_encoding::WebParamsEncode(data);
243*1a96fba6SXin Li   return PostBinaryAndBlock(url,
244*1a96fba6SXin Li                             encoded_data.c_str(),
245*1a96fba6SXin Li                             encoded_data.size(),
246*1a96fba6SXin Li                             brillo::mime::application::kWwwFormUrlEncoded,
247*1a96fba6SXin Li                             headers,
248*1a96fba6SXin Li                             transport,
249*1a96fba6SXin Li                             error);
250*1a96fba6SXin Li }
251*1a96fba6SXin Li 
PostFormDataAndBlock(const std::string & url,std::unique_ptr<FormData> form_data,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)252*1a96fba6SXin Li std::unique_ptr<Response> PostFormDataAndBlock(
253*1a96fba6SXin Li     const std::string& url,
254*1a96fba6SXin Li     std::unique_ptr<FormData> form_data,
255*1a96fba6SXin Li     const HeaderList& headers,
256*1a96fba6SXin Li     std::shared_ptr<Transport> transport,
257*1a96fba6SXin Li     brillo::ErrorPtr* error) {
258*1a96fba6SXin Li   Request request(url, request_type::kPost, transport);
259*1a96fba6SXin Li   request.AddHeaders(headers);
260*1a96fba6SXin Li   if (!request.AddRequestBodyAsFormData(std::move(form_data), error))
261*1a96fba6SXin Li     return std::unique_ptr<Response>();
262*1a96fba6SXin Li   return request.GetResponseAndBlock(error);
263*1a96fba6SXin Li }
264*1a96fba6SXin Li 
PostFormData(const std::string & url,const FormFieldList & data,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)265*1a96fba6SXin Li RequestID PostFormData(const std::string& url,
266*1a96fba6SXin Li                        const FormFieldList& data,
267*1a96fba6SXin Li                        const HeaderList& headers,
268*1a96fba6SXin Li                        std::shared_ptr<Transport> transport,
269*1a96fba6SXin Li                        const SuccessCallback& success_callback,
270*1a96fba6SXin Li                        const ErrorCallback& error_callback) {
271*1a96fba6SXin Li   std::string encoded_data = brillo::data_encoding::WebParamsEncode(data);
272*1a96fba6SXin Li   return PostBinary(url,
273*1a96fba6SXin Li                     encoded_data.c_str(),
274*1a96fba6SXin Li                     encoded_data.size(),
275*1a96fba6SXin Li                     brillo::mime::application::kWwwFormUrlEncoded,
276*1a96fba6SXin Li                     headers,
277*1a96fba6SXin Li                     transport,
278*1a96fba6SXin Li                     success_callback,
279*1a96fba6SXin Li                     error_callback);
280*1a96fba6SXin Li }
281*1a96fba6SXin Li 
PostFormData(const std::string & url,std::unique_ptr<FormData> form_data,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)282*1a96fba6SXin Li RequestID PostFormData(const std::string& url,
283*1a96fba6SXin Li                        std::unique_ptr<FormData> form_data,
284*1a96fba6SXin Li                        const HeaderList& headers,
285*1a96fba6SXin Li                        std::shared_ptr<Transport> transport,
286*1a96fba6SXin Li                        const SuccessCallback& success_callback,
287*1a96fba6SXin Li                        const ErrorCallback& error_callback) {
288*1a96fba6SXin Li   Request request(url, request_type::kPost, transport);
289*1a96fba6SXin Li   request.AddHeaders(headers);
290*1a96fba6SXin Li   brillo::ErrorPtr error;
291*1a96fba6SXin Li   if (!request.AddRequestBodyAsFormData(std::move(form_data), &error)) {
292*1a96fba6SXin Li     transport->RunCallbackAsync(
293*1a96fba6SXin Li         FROM_HERE, base::Bind(error_callback, 0, base::Owned(error.release())));
294*1a96fba6SXin Li     return 0;
295*1a96fba6SXin Li   }
296*1a96fba6SXin Li   return request.GetResponse(success_callback, error_callback);
297*1a96fba6SXin Li }
298*1a96fba6SXin Li 
PostJsonAndBlock(const std::string & url,const base::Value * json,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)299*1a96fba6SXin Li std::unique_ptr<Response> PostJsonAndBlock(const std::string& url,
300*1a96fba6SXin Li                                            const base::Value* json,
301*1a96fba6SXin Li                                            const HeaderList& headers,
302*1a96fba6SXin Li                                            std::shared_ptr<Transport> transport,
303*1a96fba6SXin Li                                            brillo::ErrorPtr* error) {
304*1a96fba6SXin Li   std::string data;
305*1a96fba6SXin Li   if (json)
306*1a96fba6SXin Li     base::JSONWriter::Write(*json, &data);
307*1a96fba6SXin Li   std::string mime_type = AppendParameter(brillo::mime::application::kJson,
308*1a96fba6SXin Li                                           brillo::mime::parameters::kCharset,
309*1a96fba6SXin Li                                           "utf-8");
310*1a96fba6SXin Li   return PostBinaryAndBlock(
311*1a96fba6SXin Li       url, data.c_str(), data.size(), mime_type, headers, transport, error);
312*1a96fba6SXin Li }
313*1a96fba6SXin Li 
PostJson(const std::string & url,std::unique_ptr<base::Value> json,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)314*1a96fba6SXin Li RequestID PostJson(const std::string& url,
315*1a96fba6SXin Li                    std::unique_ptr<base::Value> json,
316*1a96fba6SXin Li                    const HeaderList& headers,
317*1a96fba6SXin Li                    std::shared_ptr<Transport> transport,
318*1a96fba6SXin Li                    const SuccessCallback& success_callback,
319*1a96fba6SXin Li                    const ErrorCallback& error_callback) {
320*1a96fba6SXin Li   std::string data;
321*1a96fba6SXin Li   if (json)
322*1a96fba6SXin Li     base::JSONWriter::Write(*json, &data);
323*1a96fba6SXin Li   std::string mime_type = AppendParameter(brillo::mime::application::kJson,
324*1a96fba6SXin Li                                           brillo::mime::parameters::kCharset,
325*1a96fba6SXin Li                                           "utf-8");
326*1a96fba6SXin Li   return PostBinary(url,
327*1a96fba6SXin Li                     data.c_str(),
328*1a96fba6SXin Li                     data.size(),
329*1a96fba6SXin Li                     mime_type,
330*1a96fba6SXin Li                     headers,
331*1a96fba6SXin Li                     transport,
332*1a96fba6SXin Li                     success_callback,
333*1a96fba6SXin Li                     error_callback);
334*1a96fba6SXin Li }
335*1a96fba6SXin Li 
PatchJsonAndBlock(const std::string & url,const base::Value * json,const HeaderList & headers,std::shared_ptr<Transport> transport,brillo::ErrorPtr * error)336*1a96fba6SXin Li std::unique_ptr<Response> PatchJsonAndBlock(
337*1a96fba6SXin Li     const std::string& url,
338*1a96fba6SXin Li     const base::Value* json,
339*1a96fba6SXin Li     const HeaderList& headers,
340*1a96fba6SXin Li     std::shared_ptr<Transport> transport,
341*1a96fba6SXin Li     brillo::ErrorPtr* error) {
342*1a96fba6SXin Li   std::string data;
343*1a96fba6SXin Li   if (json)
344*1a96fba6SXin Li     base::JSONWriter::Write(*json, &data);
345*1a96fba6SXin Li   std::string mime_type = AppendParameter(brillo::mime::application::kJson,
346*1a96fba6SXin Li                                           brillo::mime::parameters::kCharset,
347*1a96fba6SXin Li                                           "utf-8");
348*1a96fba6SXin Li   return SendRequestAndBlock(request_type::kPatch,
349*1a96fba6SXin Li                              url,
350*1a96fba6SXin Li                              data.c_str(),
351*1a96fba6SXin Li                              data.size(),
352*1a96fba6SXin Li                              mime_type,
353*1a96fba6SXin Li                              headers,
354*1a96fba6SXin Li                              transport,
355*1a96fba6SXin Li                              error);
356*1a96fba6SXin Li }
357*1a96fba6SXin Li 
PatchJson(const std::string & url,std::unique_ptr<base::Value> json,const HeaderList & headers,std::shared_ptr<Transport> transport,const SuccessCallback & success_callback,const ErrorCallback & error_callback)358*1a96fba6SXin Li RequestID PatchJson(const std::string& url,
359*1a96fba6SXin Li                     std::unique_ptr<base::Value> json,
360*1a96fba6SXin Li                     const HeaderList& headers,
361*1a96fba6SXin Li                     std::shared_ptr<Transport> transport,
362*1a96fba6SXin Li                     const SuccessCallback& success_callback,
363*1a96fba6SXin Li                     const ErrorCallback& error_callback) {
364*1a96fba6SXin Li   std::string data;
365*1a96fba6SXin Li   if (json)
366*1a96fba6SXin Li     base::JSONWriter::Write(*json, &data);
367*1a96fba6SXin Li   std::string mime_type =
368*1a96fba6SXin Li       AppendParameter(brillo::mime::application::kJson,
369*1a96fba6SXin Li                       brillo::mime::parameters::kCharset, "utf-8");
370*1a96fba6SXin Li   return SendRequest(request_type::kPatch, url, data.c_str(), data.size(),
371*1a96fba6SXin Li                      mime_type, headers, transport, success_callback,
372*1a96fba6SXin Li                      error_callback);
373*1a96fba6SXin Li }
374*1a96fba6SXin Li 
ParseJsonResponse(Response * response,int * status_code,brillo::ErrorPtr * error)375*1a96fba6SXin Li std::unique_ptr<base::DictionaryValue> ParseJsonResponse(
376*1a96fba6SXin Li     Response* response,
377*1a96fba6SXin Li     int* status_code,
378*1a96fba6SXin Li     brillo::ErrorPtr* error) {
379*1a96fba6SXin Li   std::unique_ptr<base::DictionaryValue> result;
380*1a96fba6SXin Li   if (!response)
381*1a96fba6SXin Li     return result;
382*1a96fba6SXin Li 
383*1a96fba6SXin Li   if (status_code)
384*1a96fba6SXin Li     *status_code = response->GetStatusCode();
385*1a96fba6SXin Li 
386*1a96fba6SXin Li   // Make sure we have a correct content type. Do not try to parse
387*1a96fba6SXin Li   // binary files, or HTML output. Limit to application/json and text/plain.
388*1a96fba6SXin Li   auto content_type = RemoveParameters(response->GetContentType());
389*1a96fba6SXin Li   if (content_type != brillo::mime::application::kJson &&
390*1a96fba6SXin Li       content_type != brillo::mime::text::kPlain) {
391*1a96fba6SXin Li     brillo::Error::AddTo(error, FROM_HERE, brillo::errors::json::kDomain,
392*1a96fba6SXin Li                          "non_json_content_type",
393*1a96fba6SXin Li                          "Unexpected response content type: " + content_type);
394*1a96fba6SXin Li     return result;
395*1a96fba6SXin Li   }
396*1a96fba6SXin Li 
397*1a96fba6SXin Li   std::string json = response->ExtractDataAsString();
398*1a96fba6SXin Li   std::string error_message;
399*1a96fba6SXin Li   auto value = base::JSONReader::ReadAndReturnError(json, base::JSON_PARSE_RFC,
400*1a96fba6SXin Li                                                     nullptr, &error_message);
401*1a96fba6SXin Li   if (!value) {
402*1a96fba6SXin Li     brillo::Error::AddToPrintf(error, FROM_HERE, brillo::errors::json::kDomain,
403*1a96fba6SXin Li                                brillo::errors::json::kParseError,
404*1a96fba6SXin Li                                "Error '%s' occurred parsing JSON string '%s'",
405*1a96fba6SXin Li                                error_message.c_str(), json.c_str());
406*1a96fba6SXin Li     return result;
407*1a96fba6SXin Li   }
408*1a96fba6SXin Li   result = base::DictionaryValue::From(std::move(value));
409*1a96fba6SXin Li   if (!result) {
410*1a96fba6SXin Li     brillo::Error::AddToPrintf(error, FROM_HERE, brillo::errors::json::kDomain,
411*1a96fba6SXin Li                                brillo::errors::json::kObjectExpected,
412*1a96fba6SXin Li                                "Response is not a valid JSON object: '%s'",
413*1a96fba6SXin Li                                json.c_str());
414*1a96fba6SXin Li   }
415*1a96fba6SXin Li   return result;
416*1a96fba6SXin Li }
417*1a96fba6SXin Li 
GetCanonicalHeaderName(const std::string & name)418*1a96fba6SXin Li std::string GetCanonicalHeaderName(const std::string& name) {
419*1a96fba6SXin Li   std::string canonical_name = name;
420*1a96fba6SXin Li   bool word_begin = true;
421*1a96fba6SXin Li   for (char& c : canonical_name) {
422*1a96fba6SXin Li     if (c == '-') {
423*1a96fba6SXin Li       word_begin = true;
424*1a96fba6SXin Li     } else {
425*1a96fba6SXin Li       if (word_begin) {
426*1a96fba6SXin Li         c = toupper(c);
427*1a96fba6SXin Li       } else {
428*1a96fba6SXin Li         c = tolower(c);
429*1a96fba6SXin Li       }
430*1a96fba6SXin Li       word_begin = false;
431*1a96fba6SXin Li     }
432*1a96fba6SXin Li   }
433*1a96fba6SXin Li   return canonical_name;
434*1a96fba6SXin Li }
435*1a96fba6SXin Li 
436*1a96fba6SXin Li }  // namespace http
437*1a96fba6SXin Li }  // namespace brillo
438