blob: d711cf81af1600bfbdeeca594dcc3fd90e8daeb7 [file] [log] [blame]
Chris Sosa45d9f102014-03-24 11:18:54 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "buffet/http_utils.h"
6
7#include <algorithm>
8#include <string.h>
9#include <base/values.h>
10#include <base/json/json_reader.h>
11#include <base/json/json_writer.h>
12
Alex Vakulenkob645cc92014-04-15 11:34:35 -070013#include "buffet/mime_utils.h"
14#include "buffet/data_encoding.h"
Chris Sosa45d9f102014-03-24 11:18:54 -070015
16namespace chromeos {
17namespace http {
18
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070019std::unique_ptr<Response> Get(const std::string& url,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070020 const HeaderList& headers,
21 std::shared_ptr<Transport> transport) {
22 return SendRequest(request_type::kGet, url, nullptr, 0, nullptr,
23 headers, transport);
Chris Sosa45d9f102014-03-24 11:18:54 -070024}
25
Alex Vakulenko3cb466c2014-04-15 11:36:32 -070026std::string GetAsString(const std::string& url,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070027 const HeaderList& headers,
28 std::shared_ptr<Transport> transport) {
29 auto resp = Get(url, headers, transport);
Chris Sosa45d9f102014-03-24 11:18:54 -070030 return resp ? resp->GetDataAsString() : std::string();
31}
32
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070033std::unique_ptr<Response> Head(const std::string& url,
34 std::shared_ptr<Transport> transport) {
35 Request request(url, request_type::kHead, transport);
Chris Sosa45d9f102014-03-24 11:18:54 -070036 return request.GetResponse();
37}
38
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070039std::unique_ptr<Response> PostText(const std::string& url,
40 const char* data,
41 const char* mime_type,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070042 const HeaderList& headers,
43 std::shared_ptr<Transport> transport) {
Chris Sosa45d9f102014-03-24 11:18:54 -070044 if (mime_type == nullptr) {
45 mime_type = chromeos::mime::application::kWwwFormUrlEncoded;
46 }
47
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070048 return PostBinary(url, data, strlen(data), mime_type, headers, transport);
Chris Sosa45d9f102014-03-24 11:18:54 -070049}
50
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070051std::unique_ptr<Response> SendRequest(const char * method,
52 const std::string& url,
53 const void* data,
Alex Vakulenkob645cc92014-04-15 11:34:35 -070054 size_t data_size,
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070055 const char* mime_type,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070056 const HeaderList& headers,
57 std::shared_ptr<Transport> transport) {
58 Request request(url, method, transport);
Alex Vakulenkob645cc92014-04-15 11:34:35 -070059 request.AddHeaders(headers);
60 if (data_size > 0) {
61 if (mime_type == nullptr) {
62 mime_type = chromeos::mime::application::kOctet_stream;
63 }
64 request.SetContentType(mime_type);
65 request.AddRequestBody(data, data_size);
Chris Sosa45d9f102014-03-24 11:18:54 -070066 }
Chris Sosa45d9f102014-03-24 11:18:54 -070067 return request.GetResponse();
68}
69
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070070std::unique_ptr<Response> PostBinary(const std::string & url, const void* data,
71 size_t data_size, const char* mime_type,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070072 const HeaderList& headers,
73 std::shared_ptr<Transport> transport) {
Alex Vakulenkob645cc92014-04-15 11:34:35 -070074 return SendRequest(request_type::kPost, url,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070075 data, data_size, mime_type, headers, transport);
Chris Sosa45d9f102014-03-24 11:18:54 -070076}
77
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070078std::unique_ptr<Response> PostFormData(const std::string& url,
79 const FormFieldList& data,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070080 const HeaderList& headers,
81 std::shared_ptr<Transport> transport) {
Alex Vakulenkob645cc92014-04-15 11:34:35 -070082 std::string encoded_data = chromeos::data_encoding::WebParamsEncode(data);
83 return PostBinary(url, encoded_data.c_str(), encoded_data.size(),
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070084 chromeos::mime::application::kWwwFormUrlEncoded,
85 headers, transport);
Alex Vakulenkob645cc92014-04-15 11:34:35 -070086}
87
88
Alex Vakulenkob8ba5952014-04-17 11:35:56 -070089std::unique_ptr<Response> PostJson(const std::string& url,
90 const base::Value* json,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -070091 const HeaderList& headers,
92 std::shared_ptr<Transport> transport) {
Alex Vakulenkob645cc92014-04-15 11:34:35 -070093 std::string data;
94 if (json)
95 base::JSONWriter::Write(json, &data);
Alex Vakulenko8e34d392014-04-29 11:02:56 -070096 std::string mime_type = mime::AppendParameter(mime::application::kJson,
97 mime::parameters::kCharset,
98 "utf-8");
Alex Vakulenkob645cc92014-04-15 11:34:35 -070099 return PostBinary(url, data.c_str(), data.size(),
Alex Vakulenko8e34d392014-04-29 11:02:56 -0700100 mime_type.c_str(), headers, transport);
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700101}
102
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700103std::unique_ptr<Response> PatchJson(const std::string& url,
104 const base::Value* json,
Alex Vakulenkoa3062c52014-04-21 17:05:51 -0700105 const HeaderList& headers,
106 std::shared_ptr<Transport> transport) {
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700107 std::string data;
108 if (json)
109 base::JSONWriter::Write(json, &data);
Alex Vakulenko8e34d392014-04-29 11:02:56 -0700110 std::string mime_type = mime::AppendParameter(mime::application::kJson,
111 mime::parameters::kCharset,
112 "utf-8");
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700113 return SendRequest(request_type::kPatch, url, data.c_str(), data.size(),
Alex Vakulenko8e34d392014-04-29 11:02:56 -0700114 mime_type.c_str(), headers, transport);
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700115}
116
117std::unique_ptr<base::DictionaryValue> ParseJsonResponse(
Alex Vakulenkob8ba5952014-04-17 11:35:56 -0700118 const Response* response, int* status_code, std::string* error_message) {
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700119 std::unique_ptr<base::DictionaryValue> dict;
Chris Sosa45d9f102014-03-24 11:18:54 -0700120 if (response) {
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700121 if (status_code)
122 *status_code = response->GetStatusCode();
123
124 // Make sure we have a correct content type. Do not try to parse
125 // binary files, or HTML output. Limit to application/json and text/plain.
126 auto content_type = mime::RemoveParameters(response->GetContentType());
127 if (content_type == mime::application::kJson ||
128 content_type == mime::text::kPlain) {
129 std::string json = response->GetDataAsString();
130 auto value = base::JSONReader::ReadAndReturnError(json,
131 base::JSON_PARSE_RFC,
132 nullptr,
133 error_message);
134 if (value) {
135 base::DictionaryValue* dict_value = nullptr;
136 if (value->GetAsDictionary(&dict_value)) {
137 dict.reset(dict_value);
138 } else {
139 delete value;
140 if (error_message) {
141 *error_message = "Reponse is not a valid JSON object";
142 }
143 }
Chris Sosa45d9f102014-03-24 11:18:54 -0700144 }
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700145 }
146 else if (error_message) {
147 *error_message = "Unexpected response content type: " + content_type;
Chris Sosa45d9f102014-03-24 11:18:54 -0700148 }
149 } else if (error_message) {
150 *error_message = "NULL response.";
151 }
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700152 return dict;
Chris Sosa45d9f102014-03-24 11:18:54 -0700153}
154
155} // namespace http
156} // namespace chromeos