blob: 09442f1c463c5db0f0a36d5e2a2d12e7d6bdfae9 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <gutil/strings/substitute.h>
#include <iosfwd>
#include <map>
#include <string>
#include "common/status.h"
#include "gflags/gflags_declare.h"
DECLARE_int32(webserver_port);
using boost::asio::ip::tcp;
namespace impala {
struct HttpRequest {
std::string url_path = "/";
std::string host = "localhost";
int32_t port = FLAGS_webserver_port;
std::map<std::string, std::string> headers = {};
// Adapted from:
// http://stackoverflow.com/questions/10982717/get-html-without-header-with-boostasio
Status Do(std::ostream* out, int expected_code, const std::string& method) {
try {
tcp::iostream request_stream;
request_stream.connect(host, boost::lexical_cast<std::string>(port));
if (!request_stream) return Status("Could not connect request_stream");
request_stream << method << " " << url_path << " HTTP/1.1\r\n";
request_stream << "Host: " << host << ":" << port << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Cache-Control: no-cache\r\n";
if (method == "POST") {
request_stream << "Content-Length: 0\r\n";
}
for (const auto& header : headers) {
request_stream << header.first << ": " << header.second << "\r\n";
}
request_stream << "Connection: close\r\n\r\n";
request_stream.flush();
std::string line1;
getline(request_stream, line1);
if (!request_stream) return Status("No response");
std::stringstream response_stream(line1);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
getline(response_stream, status_message);
if (!response_stream || http_version.substr(0,5) != "HTTP/") {
return Status("Malformed response");
}
if (status_code != expected_code) {
return Status(strings::Substitute("Unexpected status code: $0", status_code));
}
(*out) << request_stream.rdbuf();
return Status::OK();
} catch (const std::exception& e){
return Status(e.what());
}
}
Status Get(ostream* out, int expected_code = 200) {
return Do(out, expected_code, "GET");
}
Status Post(ostream* out, int expected_code = 200) {
return Do(out, expected_code, "POST");
}
}; // struct HttpRequest
Status HttpGet(const std::string& host, const int32_t& port, const std::string& url_path,
ostream* out, int expected_code = 200, const std::string& method = "GET") {
return HttpRequest{url_path, host, port}.Do(out, expected_code, method);
}
} // namespace impala