1f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// Copyright 2014 The Chromium OS Authors. All rights reserved. 2f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// Use of this source code is governed by a BSD-style license that can be 3f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// found in the LICENSE file. 4f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 5b57c2eebc4050087576f55e02deb47b0839fb467Bertrand SIMONNET#include <numeric> 6f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko#include <string> 7f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko#include <vector> 8f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 9f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko#include <base/values.h> 109ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/bind_lambda.h> 119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/http/http_transport_fake.h> 129ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/http/http_utils.h> 139ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/mime_utils.h> 149ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/strings/string_utils.h> 159ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/url_utils.h> 16f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko#include <gtest/gtest.h> 17f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 189ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo { 19f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkonamespace http { 20f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 21f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkostatic const char kFakeUrl[] = "http://localhost"; 22f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkostatic const char kEchoUrl[] = "http://localhost/echo"; 23f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkostatic const char kMethodEchoUrl[] = "http://localhost/echo/method"; 24f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 25f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko///////////////////// Generic helper request handlers ///////////////////////// 26f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// Returns the request data back with the same content type. 27f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkostatic void EchoDataHandler(const fake::ServerRequest& request, 28f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko fake::ServerResponse* response) { 2905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko response->Reply(status_code::Ok, 3005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko request.GetData(), 312e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko request.GetHeader(request_header::kContentType)); 32f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 33f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 34f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko// Returns the request method as a plain text response. 35f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenkostatic void EchoMethodHandler(const fake::ServerRequest& request, 36f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko fake::ServerResponse* response) { 3705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko response->ReplyText( 389ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko status_code::Ok, request.GetMethod(), brillo::mime::text::kPlain); 39f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 40f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 41f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko/////////////////////////////////////////////////////////////////////////////// 42f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, SendRequest_BinaryData) { 43f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 4405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport->AddHandler( 4505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kEchoUrl, request_type::kPost, base::Bind(EchoDataHandler)); 46f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 47f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Test binary data round-tripping. 48f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko std::vector<uint8_t> custom_data{0xFF, 0x00, 0x80, 0x40, 0xC0, 0x7F}; 4905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto response = 5005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko http::SendRequestAndBlock(request_type::kPost, 5105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kEchoUrl, 5205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko custom_data.data(), 5305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko custom_data.size(), 549ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::mime::application::kOctet_stream, 5505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 5605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 5705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko nullptr); 58f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 599ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::application::kOctet_stream, 60f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko response->GetContentType()); 6120d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(custom_data, response->ExtractData()); 62f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 63f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 64f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST(HttpUtils, SendRequestAsync_BinaryData) { 65f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 6605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport->AddHandler( 6705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kEchoUrl, request_type::kPost, base::Bind(EchoDataHandler)); 68f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko 69f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko // Test binary data round-tripping. 70f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko std::vector<uint8_t> custom_data{0xFF, 0x00, 0x80, 0x40, 0xC0, 0x7F}; 71ac3059d5edad2af5a75184d1e31133e712c91f60Alex Vakulenko auto success_callback = 722fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley [&custom_data](RequestID /* id */, 732fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley std::unique_ptr<http::Response> response) { 74f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 759ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::application::kOctet_stream, 76f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko response->GetContentType()); 7720d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(custom_data, response->ExtractData()); 78f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko }; 792fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley auto error_callback = [](RequestID /* id */, const Error* /* error */) { 80f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko FAIL() << "This callback shouldn't have been called"; 81f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko }; 8205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko http::SendRequest(request_type::kPost, 8305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kEchoUrl, 8405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko custom_data.data(), 8505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko custom_data.size(), 869ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::mime::application::kOctet_stream, 8705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 8805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 8905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko base::Bind(success_callback), 9005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko base::Bind(error_callback)); 91f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko} 92f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko 93f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, SendRequest_Post) { 94f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 95f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kMethodEchoUrl, "*", base::Bind(EchoMethodHandler)); 96f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 97f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Test binary data round-tripping. 98f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko std::vector<uint8_t> custom_data{0xFF, 0x00, 0x80, 0x40, 0xC0, 0x7F}; 99f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 100f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Check the correct HTTP method used. 10105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto response = 10205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko http::SendRequestAndBlock(request_type::kPost, 10305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kMethodEchoUrl, 10405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko custom_data.data(), 10505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko custom_data.size(), 1069ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::mime::application::kOctet_stream, 10705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 10805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 10905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko nullptr); 110f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 1119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::text::kPlain, response->GetContentType()); 11220d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(request_type::kPost, response->ExtractDataAsString()); 113f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 114f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 115f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, SendRequest_Get) { 116f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 117f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kMethodEchoUrl, "*", base::Bind(EchoMethodHandler)); 118f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 11905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto response = http::SendRequestAndBlock(request_type::kGet, 12005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kMethodEchoUrl, 12105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko nullptr, 12205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko 0, 12305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko std::string{}, 12405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 12505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 12605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko nullptr); 127f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 1289ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::text::kPlain, response->GetContentType()); 12920d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(request_type::kGet, response->ExtractDataAsString()); 130f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 131f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 132f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, SendRequest_Put) { 133f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 134f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kMethodEchoUrl, "*", base::Bind(EchoMethodHandler)); 135f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 13605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto response = http::SendRequestAndBlock(request_type::kPut, 13705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kMethodEchoUrl, 13805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko nullptr, 13905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko 0, 14005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko std::string{}, 14105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 14205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 14305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko nullptr); 144f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 1459ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::text::kPlain, response->GetContentType()); 14620d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(request_type::kPut, response->ExtractDataAsString()); 147f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 148f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 149f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, SendRequest_NotFound) { 150f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 151f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Test failed response (URL not found). 152f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko auto response = http::SendRequestWithNoDataAndBlock( 153f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko request_type::kGet, "http://blah.com", {}, transport, nullptr); 154f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_FALSE(response->IsSuccessful()); 155f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(status_code::NotFound, response->GetStatusCode()); 156f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 157f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 158f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST(HttpUtils, SendRequestAsync_NotFound) { 159f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 160f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko // Test failed response (URL not found). 161ac3059d5edad2af5a75184d1e31133e712c91f60Alex Vakulenko auto success_callback = 1622fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley [](RequestID /* request_id */, std::unique_ptr<http::Response> response) { 163f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_FALSE(response->IsSuccessful()); 164f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_EQ(status_code::NotFound, response->GetStatusCode()); 165f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko }; 1662fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley auto error_callback = [](RequestID /* request_id */, 1672fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley const Error* /* error */) { 168f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko FAIL() << "This callback shouldn't have been called"; 169f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko }; 17005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko http::SendRequestWithNoData(request_type::kGet, 17105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko "http://blah.com", 17205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 17305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 17405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko base::Bind(success_callback), 17505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko base::Bind(error_callback)); 176f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko} 177f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko 178f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, SendRequest_Headers) { 179f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 180f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 181f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko static const char json_echo_url[] = "http://localhost/echo/json"; 18205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto JsonEchoHandler = 18305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko [](const fake::ServerRequest& request, fake::ServerResponse* response) { 184f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko base::DictionaryValue json; 185f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko json.SetString("method", request.GetMethod()); 186f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko json.SetString("data", request.GetDataAsString()); 187f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko for (const auto& pair : request.GetHeaders()) { 188f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko json.SetString("header." + pair.first, pair.second); 189f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko } 190f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko response->ReplyJson(status_code::Ok, &json); 191f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko }; 19205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport->AddHandler(json_echo_url, "*", base::Bind(JsonEchoHandler)); 1932e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko auto response = http::SendRequestAndBlock( 194f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko request_type::kPost, json_echo_url, "abcd", 4, 1959ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::mime::application::kOctet_stream, { 196f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko {request_header::kCookie, "flavor=vanilla"}, 197f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko {request_header::kIfMatch, "*"}, 198f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko }, transport, nullptr); 199f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 2009ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::application::kJson, 2019ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::mime::RemoveParameters(response->GetContentType())); 202f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko auto json = ParseJsonResponse(response.get(), nullptr, nullptr); 203f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::string value; 204f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(json->GetString("method", &value)); 205f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(request_type::kPost, value); 206f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(json->GetString("data", &value)); 207f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("abcd", value); 208f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(json->GetString("header.Cookie", &value)); 209f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("flavor=vanilla", value); 210f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(json->GetString("header.Content-Type", &value)); 2119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::application::kOctet_stream, value); 212f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(json->GetString("header.Content-Length", &value)); 213f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("4", value); 214f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(json->GetString("header.If-Match", &value)); 215f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("*", value); 216f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 217f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 218f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, Get) { 219f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Sends back the "?test=..." portion of URL. 220f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // So if we do GET "http://localhost?test=blah", this handler responds 221f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // with "blah" as text/plain. 22205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto GetHandler = 22305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko [](const fake::ServerRequest& request, fake::ServerResponse* response) { 224f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(request_type::kGet, request.GetMethod()); 225f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("0", request.GetHeader(request_header::kContentLength)); 226f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("", request.GetHeader(request_header::kContentType)); 22705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko response->ReplyText(status_code::Ok, 22805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko request.GetFormField("test"), 2299ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::mime::text::kPlain); 230f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko }; 231f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 232f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 233f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kFakeUrl, request_type::kGet, base::Bind(GetHandler)); 234f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kMethodEchoUrl, "*", base::Bind(EchoMethodHandler)); 235f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 236d360e9b5f7549eecf5651ab58a5d766a095caf2eAlex Vakulenko // Make sure Get() actually does the GET request 2372e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko auto response = http::GetAndBlock(kMethodEchoUrl, {}, transport, nullptr); 238f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 2399ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::text::kPlain, response->GetContentType()); 24020d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(request_type::kGet, response->ExtractDataAsString()); 241f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 242f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko for (std::string data : {"blah", "some data", ""}) { 2439ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko std::string url = brillo::url::AppendQueryParam(kFakeUrl, "test", data); 244d360e9b5f7549eecf5651ab58a5d766a095caf2eAlex Vakulenko response = http::GetAndBlock(url, {}, transport, nullptr); 24520d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(data, response->ExtractDataAsString()); 246f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko } 247f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 248f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 249f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, Head) { 25005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto HeadHandler = 25105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko [](const fake::ServerRequest& request, fake::ServerResponse* response) { 252f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(request_type::kHead, request.GetMethod()); 253f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("0", request.GetHeader(request_header::kContentLength)); 254f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("", request.GetHeader(request_header::kContentType)); 2559ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko response->ReplyText(status_code::Ok, "blah", brillo::mime::text::kPlain); 256f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko }; 257f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 258f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 259f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kFakeUrl, request_type::kHead, base::Bind(HeadHandler)); 260f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 2612e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko auto response = http::HeadAndBlock(kFakeUrl, transport, nullptr); 262f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 2639ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::text::kPlain, response->GetContentType()); 26420d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ("", response->ExtractDataAsString()); // Must not have actual body. 265f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("4", response->GetHeader(request_header::kContentLength)); 266f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 267f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 268f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, PostBinary) { 26905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto Handler = 27005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko [](const fake::ServerRequest& request, fake::ServerResponse* response) { 271f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(request_type::kPost, request.GetMethod()); 272f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("256", request.GetHeader(request_header::kContentLength)); 2739ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::application::kOctet_stream, 274f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko request.GetHeader(request_header::kContentType)); 275f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko const auto& data = request.GetData(); 276f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(256, data.size()); 277f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 278f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Sum up all the bytes. 279f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko int sum = std::accumulate(data.begin(), data.end(), 0); 280f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(32640, sum); // sum(i, i => [0, 255]) = 32640. 2819ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko response->ReplyText(status_code::Ok, "", brillo::mime::text::kPlain); 282f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko }; 283f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 284f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 285f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kFakeUrl, request_type::kPost, base::Bind(Handler)); 286f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 287f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko /// Fill the data buffer with bytes from 0x00 to 0xFF. 288f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko std::vector<uint8_t> data(256); 289f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::iota(data.begin(), data.end(), 0); 290f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 29105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto response = http::PostBinaryAndBlock(kFakeUrl, 29205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko data.data(), 29305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko data.size(), 29405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko mime::application::kOctet_stream, 29505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 29605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 29705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko nullptr); 298f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 299f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 300f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 301f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, PostText) { 302f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::string fake_data = "Some data"; 303f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko auto PostHandler = [fake_data](const fake::ServerRequest& request, 304f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko fake::ServerResponse* response) { 305f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(request_type::kPost, request.GetMethod()); 306f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(fake_data.size(), 307f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::stoul(request.GetHeader(request_header::kContentLength))); 3089ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::text::kPlain, 309f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko request.GetHeader(request_header::kContentType)); 31005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko response->ReplyText(status_code::Ok, 31105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko request.GetDataAsString(), 3129ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::mime::text::kPlain); 313f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko }; 314f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 315f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 316f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kFakeUrl, request_type::kPost, base::Bind(PostHandler)); 317f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 31805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto response = http::PostTextAndBlock(kFakeUrl, 31905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko fake_data, 3209ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko brillo::mime::text::kPlain, 32105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 32205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 32305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko nullptr); 324f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 3259ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::text::kPlain, response->GetContentType()); 32620d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(fake_data, response->ExtractDataAsString()); 327f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 328f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 329f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, PostFormData) { 330f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 33105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport->AddHandler( 33205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kFakeUrl, request_type::kPost, base::Bind(EchoDataHandler)); 333f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 3342e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko auto response = http::PostFormDataAndBlock( 3352e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko kFakeUrl, { 3362e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko {"key", "value"}, 3372e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko {"field", "field value"}, 3382e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko }, {}, transport, nullptr); 339f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 3409ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::application::kWwwFormUrlEncoded, 341f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko response->GetContentType()); 34220d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ("key=value&field=field+value", response->ExtractDataAsString()); 343f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 344f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 34547e9a9dd3dce9d197820ee4241135e6859f95360Alex VakulenkoTEST(HttpUtils, PostMultipartFormData) { 34647e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 34705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport->AddHandler( 34805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kFakeUrl, request_type::kPost, base::Bind(EchoDataHandler)); 34947e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko 35047e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko std::unique_ptr<FormData> form_data{new FormData{"boundary123"}}; 35147e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko form_data->AddTextField("key1", "value1"); 35247e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko form_data->AddTextField("key2", "value2"); 35347e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko std::string expected_content_type = form_data->GetContentType(); 35405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto response = http::PostFormDataAndBlock( 35505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko kFakeUrl, std::move(form_data), {}, transport, nullptr); 35647e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko EXPECT_TRUE(response->IsSuccessful()); 35747e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko EXPECT_EQ(expected_content_type, response->GetContentType()); 35847e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko const char expected_value[] = 35947e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "--boundary123\r\n" 36047e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "Content-Disposition: form-data; name=\"key1\"\r\n" 36147e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "\r\n" 36247e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "value1\r\n" 36347e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "--boundary123\r\n" 36447e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "Content-Disposition: form-data; name=\"key2\"\r\n" 36547e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "\r\n" 36647e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "value2\r\n" 36747e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko "--boundary123--"; 36820d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko EXPECT_EQ(expected_value, response->ExtractDataAsString()); 36947e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko} 37047e9a9dd3dce9d197820ee4241135e6859f95360Alex Vakulenko 371f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, PostPatchJson) { 37205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto JsonHandler = 37305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko [](const fake::ServerRequest& request, fake::ServerResponse* response) { 3749ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko auto mime_type = brillo::mime::RemoveParameters( 375f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko request.GetHeader(request_header::kContentType)); 3769ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::application::kJson, mime_type); 37705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko response->ReplyJson( 37805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko status_code::Ok, 37905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko { 38020d497f58d7abdec1e011cb1efadb45e53e5af0bAlex Vakulenko {"method", request.GetMethod()}, {"data", request.GetDataAsString()}, 38105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko }); 382f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko }; 383f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 384f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kFakeUrl, "*", base::Bind(JsonHandler)); 385f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 386f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko base::DictionaryValue json; 387f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko json.SetString("key1", "val1"); 388f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko json.SetString("key2", "val2"); 389f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::string value; 390f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 391f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Test POST 3922e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko auto response = 3932e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko http::PostJsonAndBlock(kFakeUrl, &json, {}, transport, nullptr); 394f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko auto resp_json = http::ParseJsonResponse(response.get(), nullptr, nullptr); 395f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_NE(nullptr, resp_json.get()); 396f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(resp_json->GetString("method", &value)); 397f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(request_type::kPost, value); 398f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(resp_json->GetString("data", &value)); 399f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("{\"key1\":\"val1\",\"key2\":\"val2\"}", value); 400f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 401f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Test PATCH 4022e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko response = http::PatchJsonAndBlock(kFakeUrl, &json, {}, transport, nullptr); 403f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko resp_json = http::ParseJsonResponse(response.get(), nullptr, nullptr); 404f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_NE(nullptr, resp_json.get()); 405f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(resp_json->GetString("method", &value)); 406f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(request_type::kPatch, value); 407f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(resp_json->GetString("data", &value)); 408f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ("{\"key1\":\"val1\",\"key2\":\"val2\"}", value); 409f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 410f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 411f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex VakulenkoTEST(HttpUtils, ParseJsonResponse) { 41205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko auto JsonHandler = 41305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko [](const fake::ServerRequest& request, fake::ServerResponse* response) { 414f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko int status_code = std::stoi(request.GetFormField("code")); 415f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko response->ReplyJson(status_code, {{"data", request.GetFormField("value")}}); 416f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko }; 417f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 418f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko transport->AddHandler(kFakeUrl, request_type::kPost, base::Bind(JsonHandler)); 419f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 420f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Test valid JSON responses (with success or error codes). 421f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko for (auto item : {"200;data", "400;wrong", "500;Internal Server error"}) { 4229ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko auto pair = brillo::string_utils::SplitAtFirst(item, ";"); 4232e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko auto response = http::PostFormDataAndBlock( 4242e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko kFakeUrl, { 4252e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko {"code", pair.first}, 4262e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko {"value", pair.second}, 4272e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko }, {}, transport, nullptr); 428f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko int code = 0; 429f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko auto json = http::ParseJsonResponse(response.get(), &code, nullptr); 430f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_NE(nullptr, json.get()); 431f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko std::string value; 432f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_TRUE(json->GetString("data", &value)); 4339ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(pair.first, brillo::string_utils::ToString(code)); 434f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(pair.second, value); 435f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko } 436f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 437f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko // Test invalid (non-JSON) response. 4382e1579107504b584d59e4ab036544369321f2a58Alex Vakulenko auto response = http::GetAndBlock("http://bad.url", {}, transport, nullptr); 439f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(status_code::NotFound, response->GetStatusCode()); 4409ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko EXPECT_EQ(brillo::mime::text::kHtml, response->GetContentType()); 441f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko int code = 0; 442f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko auto json = http::ParseJsonResponse(response.get(), &code, nullptr); 443f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(nullptr, json.get()); 444f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko EXPECT_EQ(status_code::NotFound, code); 445f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} 446f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko 447f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST(HttpUtils, SendRequest_Failure) { 448f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 449f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko transport->AddHandler(kMethodEchoUrl, "*", base::Bind(EchoMethodHandler)); 450f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko ErrorPtr error; 451f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko Error::AddTo(&error, FROM_HERE, "test_domain", "test_code", "Test message"); 452f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko transport->SetCreateConnectionError(std::move(error)); 453f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko error.reset(); // Just to make sure it is empty... 454f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko auto response = http::SendRequestWithNoDataAndBlock( 455f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko request_type::kGet, "http://blah.com", {}, transport, &error); 456f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_EQ(nullptr, response.get()); 457f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_EQ("test_domain", error->GetDomain()); 458f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_EQ("test_code", error->GetCode()); 459f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_EQ("Test message", error->GetMessage()); 460f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko} 461f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko 462f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST(HttpUtils, SendRequestAsync_Failure) { 463f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko std::shared_ptr<fake::Transport> transport(new fake::Transport); 464f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko transport->AddHandler(kMethodEchoUrl, "*", base::Bind(EchoMethodHandler)); 465f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko ErrorPtr error; 466f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko Error::AddTo(&error, FROM_HERE, "test_domain", "test_code", "Test message"); 467f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko transport->SetCreateConnectionError(std::move(error)); 468ac3059d5edad2af5a75184d1e31133e712c91f60Alex Vakulenko auto success_callback = 4692fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley [](RequestID /* request_id */, 4702fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley std::unique_ptr<http::Response> /* response */) { 471f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko FAIL() << "This callback shouldn't have been called"; 472f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko }; 4732fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley auto error_callback = [](RequestID /* request_id */, const Error* error) { 474f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_EQ("test_domain", error->GetDomain()); 475f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_EQ("test_code", error->GetCode()); 476f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko EXPECT_EQ("Test message", error->GetMessage()); 477f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko }; 47805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko http::SendRequestWithNoData(request_type::kGet, 47905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko "http://blah.com", 48005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {}, 48105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko transport, 48205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko base::Bind(success_callback), 48305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko base::Bind(error_callback)); 484f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko} 485f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko 486eff2061417e01d42b150d508d364733519a55653Alex VakulenkoTEST(HttpUtils, GetCanonicalHeaderName) { 487eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("Foo", GetCanonicalHeaderName("foo")); 488eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("Bar", GetCanonicalHeaderName("BaR")); 489eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("Baz", GetCanonicalHeaderName("BAZ")); 490eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("Foo-Bar", GetCanonicalHeaderName("foo-bar")); 491eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("Foo-Bar-Baz", GetCanonicalHeaderName("foo-Bar-BAZ")); 492eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("Foo-Bar-Baz", GetCanonicalHeaderName("FOO-BAR-BAZ")); 493eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("Foo-Bar-", GetCanonicalHeaderName("fOO-bAR-")); 494eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("-Bar", GetCanonicalHeaderName("-bAR")); 495eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("", GetCanonicalHeaderName("")); 496eff2061417e01d42b150d508d364733519a55653Alex Vakulenko EXPECT_EQ("A-B-C", GetCanonicalHeaderName("a-B-c")); 497eff2061417e01d42b150d508d364733519a55653Alex Vakulenko} 498eff2061417e01d42b150d508d364733519a55653Alex Vakulenko 499f788c95c111d0dccff735b8e02939e4e95ee2f5dAlex Vakulenko} // namespace http 5009ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko} // namespace brillo 501