blob: 9e9c54778300e6ca4a62012185c10a9f8c05889a [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "topaz/auth_providers/oauth/oauth_request_builder.h"
#include <iomanip>
#include <iostream>
#include "lib/fsl/socket/strings.h"
#include "lib/fsl/vmo/strings.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/strings/join_strings.h"
#include "src/lib/fxl/strings/string_number_conversions.h"
namespace auth_providers {
namespace oauth {
namespace http = ::fuchsia::net::oldhttp;
namespace {
std::string UrlEncode(const std::string& value) {
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;
for (char c : value) {
// Keep alphanumeric and other accepted characters intact
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '=' ||
c == '&' || c == '+') {
escaped << c;
continue;
}
// Any other characters are percent-encoded
escaped << std::uppercase;
escaped << '%' << std::setw(2) << int(static_cast<unsigned char>(c));
escaped << std::nouppercase;
}
return escaped.str();
}
} // namespace
OAuthRequestBuilder::OAuthRequestBuilder(const std::string& url,
const std::string& method)
: url_(url), method_(method) {
FXL_CHECK(!url_.empty());
FXL_CHECK(!method_.empty());
}
OAuthRequestBuilder::~OAuthRequestBuilder() {}
OAuthRequestBuilder& OAuthRequestBuilder::SetAuthorizationHeader(
const std::string& token) {
FXL_DCHECK(!token.empty());
http_headers_["Authorization"] = "Bearer " + token;
return *this;
}
OAuthRequestBuilder& OAuthRequestBuilder::SetUrlEncodedBody(
const std::string& body) {
http_headers_["content-type"] = "application/x-www-form-urlencoded";
if (body.empty()) {
return *this;
}
return SetRequestBody(UrlEncode(body));
}
OAuthRequestBuilder& OAuthRequestBuilder::SetJsonBody(const std::string& body) {
http_headers_["accept"] = "application/json";
http_headers_["content-type"] = "application/json";
return SetRequestBody(body);
}
OAuthRequestBuilder& OAuthRequestBuilder::SetQueryParams(
std::map<std::string, std::string> query_params) {
for (auto it = query_params.begin(); it != query_params.end(); ++it) {
query_string_ += (it == query_params.begin() ? "?" : "&");
query_string_ += UrlEncode(it->first) + "=" + UrlEncode(it->second);
}
return *this;
}
http::URLRequest OAuthRequestBuilder::Build() const {
fsl::SizedVmo data;
auto result = fsl::VmoFromString(request_body_, &data);
FXL_CHECK(result);
http::URLRequest request;
request.url = url_ + query_string_;
request.method = method_;
request.auto_follow_redirects = true;
request.body = http::URLBody::New();
request.body->set_buffer(std::move(data).ToTransport());
for (const auto& http_header : http_headers_) {
http::HttpHeader hdr;
hdr.name = http_header.first;
hdr.value = http_header.second;
request.headers.push_back(std::move(hdr));
}
return request;
}
OAuthRequestBuilder& OAuthRequestBuilder::SetRequestBody(
const std::string& body) {
request_body_ = body;
uint64_t data_size = request_body_.length();
if (data_size > 0)
http_headers_["content-length"] = fxl::NumberToString(data_size).data();
return *this;
}
} // namespace oauth
} // namespace auth_providers