RESTUnit.cpp 3.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//================================================================================
// Name        : RESTUnit.cpp
// Author      : Michael Ott
// Contact     : info@dcdb.it
// Copyright   : Leibniz Supercomputing Centre
// Description : Source file for RESTUnit class.
//================================================================================

//================================================================================
// This file is part of DCDB (DataCenter DataBase)
// Copyright (C) 2018-2021 Leibniz Supercomputing Centre
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//================================================================================

#include "RESTUnit.h"
29
#include "globalconfiguration.h"
30
31
32
33
34
35
36
37

#include <iostream>

#include <openssl/bio.h>
#include <openssl/err.h>

RESTUnit::RESTUnit(const std::string &name)
    : EntityInterface(name),
38
39
      _ctx(ssl::context::tlsv12_client),
      _ssl(false) {
40
41
42
43
}

RESTUnit::RESTUnit(const RESTUnit &other)
    : EntityInterface(other),
44
45
      _ctx(ssl::context::tlsv12_client),
      _ssl(false) {
46
47
48
49
50
51
52
}

RESTUnit::~RESTUnit() {
}

RESTUnit &RESTUnit::operator=(const RESTUnit &other) {
	EntityInterface::operator=(other);
53
	_ssl = other._ssl;
54
55
56
57
58
59
60

	return *this;
}

void RESTUnit::execOnInit() {
}

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
bool RESTUnit::sendRequest(const std::string &endpoint, const std::string &request, std::string &response) {
    // Look up the domain name
    tcp::resolver resolver(_ioc);
    auto const hosts = resolver.resolve(_hostname, _port);
    
    beast::ssl_stream<beast::tcp_stream> stream(_ioc, _ctx);
    // Make the connection on the IP address we get from a lookup
    beast::get_lowest_layer(stream).connect(hosts);

    if (_ssl) {
	// Set SNI Hostname (many hosts need this to handshake successfully)
	if(! SSL_set_tlsext_host_name(stream.native_handle(), _hostname.c_str()))
	{
	    beast::error_code ec{static_cast<int>(::ERR_get_error()), net::error::get_ssl_category()};
	    throw beast::system_error{ec};
76
	}
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
	
	// Perform the SSL handshake
	stream.handshake(ssl::stream_base::client);
    }

    // Set up an HTTP GET request message
    http::request<http::string_body> req{http::verb::get, _path + endpoint, 11};
    req.set(http::field::host, _hostname);
    req.body() = request;
    req.prepare_payload();

    // Send the HTTP request to the remote host
    if (_ssl) {
	http::write(stream, req);
    } else {
	http::write(beast::get_lowest_layer(stream), req);
    }

    // This buffer is used for reading and must be persisted
    beast::flat_buffer buffer;

    // Declare a container to hold the response
    http::response<http::string_body> res;

    // Receive the HTTP response
    if (_ssl) {
	http::read(stream, buffer, res);
    } else {
	http::read(beast::get_lowest_layer(stream), buffer, res);		
    }
    
    if (res.body().size() > 0) {
	response = res.body();
110
	return true;
111
112
113
    } else {
	return false;
    }
114
}