blob: 9db6b1cf76ae17c429f225a09d63f0397c19d6ed [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 Vakulenkob645cc92014-04-15 11:34:35 -070019std::unique_ptr<Response> Get(std::string const& url) {
Chris Sosa45d9f102014-03-24 11:18:54 -070020 Request request(url);
21 return request.GetResponse();
22}
23
Alex Vakulenkob645cc92014-04-15 11:34:35 -070024std::string GetAsString(std::string const& url) {
Chris Sosa45d9f102014-03-24 11:18:54 -070025 auto resp = Get(url);
26 return resp ? resp->GetDataAsString() : std::string();
27}
28
Alex Vakulenkob645cc92014-04-15 11:34:35 -070029std::unique_ptr<Response> Head(std::string const& url) {
Chris Sosa45d9f102014-03-24 11:18:54 -070030 Request request(url, request_type::kHead);
31 return request.GetResponse();
32}
33
Alex Vakulenkob645cc92014-04-15 11:34:35 -070034std::unique_ptr<Response> PostText(std::string const& url,
Chris Sosa45d9f102014-03-24 11:18:54 -070035 char const* data,
Alex Vakulenkob645cc92014-04-15 11:34:35 -070036 char const* mime_type,
37 HeaderList const& headers) {
Chris Sosa45d9f102014-03-24 11:18:54 -070038 if (mime_type == nullptr) {
39 mime_type = chromeos::mime::application::kWwwFormUrlEncoded;
40 }
41
Alex Vakulenkob645cc92014-04-15 11:34:35 -070042 return PostBinary(url, data, strlen(data), mime_type, headers);
Chris Sosa45d9f102014-03-24 11:18:54 -070043}
44
Alex Vakulenkob645cc92014-04-15 11:34:35 -070045std::unique_ptr<Response> SendRequest(char const* method,
46 std::string const& url,
47 void const* data,
48 size_t data_size,
49 char const* mime_type,
50 HeaderList const& headers) {
51 Request request(url, method);
52 request.AddHeaders(headers);
53 if (data_size > 0) {
54 if (mime_type == nullptr) {
55 mime_type = chromeos::mime::application::kOctet_stream;
56 }
57 request.SetContentType(mime_type);
58 request.AddRequestBody(data, data_size);
Chris Sosa45d9f102014-03-24 11:18:54 -070059 }
Chris Sosa45d9f102014-03-24 11:18:54 -070060 return request.GetResponse();
61}
62
Alex Vakulenkob645cc92014-04-15 11:34:35 -070063std::unique_ptr<Response> PostBinary(std::string const& url, void const* data,
64 size_t data_size, char const* mime_type,
65 HeaderList const& headers) {
66 return SendRequest(request_type::kPost, url,
67 data, data_size, mime_type, headers);
Chris Sosa45d9f102014-03-24 11:18:54 -070068}
69
Alex Vakulenkob645cc92014-04-15 11:34:35 -070070std::unique_ptr<Response> PostFormData(std::string const& url,
71 FormFieldList const& data,
72 HeaderList const& headers) {
73 std::string encoded_data = chromeos::data_encoding::WebParamsEncode(data);
74 return PostBinary(url, encoded_data.c_str(), encoded_data.size(),
75 chromeos::mime::application::kWwwFormUrlEncoded, headers);
76}
77
78
79std::unique_ptr<Response> PostJson(std::string const& url,
80 base::Value const* json,
81 HeaderList const& headers) {
82 std::string data;
83 if (json)
84 base::JSONWriter::Write(json, &data);
85 return PostBinary(url, data.c_str(), data.size(),
86 mime::application::kJson, headers);
87}
88
89std::unique_ptr<Response> PatchJson(std::string const& url,
90 base::Value const* json,
91 HeaderList const& headers) {
92 std::string data;
93 if (json)
94 base::JSONWriter::Write(json, &data);
95 return SendRequest(request_type::kPatch, url, data.c_str(), data.size(),
96 mime::application::kJson, headers);
97}
98
99std::unique_ptr<base::DictionaryValue> ParseJsonResponse(
100 Response const* response, int* status_code, std::string* error_message) {
101 std::unique_ptr<base::DictionaryValue> dict;
Chris Sosa45d9f102014-03-24 11:18:54 -0700102 if (response) {
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700103 if (status_code)
104 *status_code = response->GetStatusCode();
105
106 // Make sure we have a correct content type. Do not try to parse
107 // binary files, or HTML output. Limit to application/json and text/plain.
108 auto content_type = mime::RemoveParameters(response->GetContentType());
109 if (content_type == mime::application::kJson ||
110 content_type == mime::text::kPlain) {
111 std::string json = response->GetDataAsString();
112 auto value = base::JSONReader::ReadAndReturnError(json,
113 base::JSON_PARSE_RFC,
114 nullptr,
115 error_message);
116 if (value) {
117 base::DictionaryValue* dict_value = nullptr;
118 if (value->GetAsDictionary(&dict_value)) {
119 dict.reset(dict_value);
120 } else {
121 delete value;
122 if (error_message) {
123 *error_message = "Reponse is not a valid JSON object";
124 }
125 }
Chris Sosa45d9f102014-03-24 11:18:54 -0700126 }
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700127 }
128 else if (error_message) {
129 *error_message = "Unexpected response content type: " + content_type;
Chris Sosa45d9f102014-03-24 11:18:54 -0700130 }
131 } else if (error_message) {
132 *error_message = "NULL response.";
133 }
Alex Vakulenkob645cc92014-04-15 11:34:35 -0700134 return dict;
Chris Sosa45d9f102014-03-24 11:18:54 -0700135}
136
137} // namespace http
138} // namespace chromeos