Commit 36be4887 authored by Roy de Goei's avatar Roy de Goei

TMSS-156: First implementation of TMSSBridge using jsoncpp and curl

parent 50293588
# - Try to find readline, a library for easy editing of command lines.
# Variables used by this module:
# CURLCPP_ROOT_DIR - curl root directory
# Variables defined by this module:
# CURL_FOUND - system has curl
# CURL_INCLUDE_DIR - the curl include directory (cached)
# CURL_INCLUDE_DIRS - the curl include directories
# (identical to CURLCPP_INCLUDE_DIR)
# CURL_LIBRARY - the curl library (cached)
# CURL_LIBRARIES - the curl library
# Copyright (C) 2009
# ASTRON (Netherlands Institute for Radio Astronomy)
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
# This file is part of the LOFAR software suite.
# The LOFAR software suite 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 3 of the License, or
# (at your option) any later version.
# The LOFAR software suite is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along
# with the LOFAR software suite. If not, see <>.
# $Id$
find_path(CURL_INCLUDE_DIR curl/curl.h
HINTS ${CURL_ROOT_DIR} PATH_SUFFIXES include) # curl headers
find_library(CURL_LIBRARY curl) # libcurl
find_package_handle_standard_args(curl DEFAULT_MSG
# $Id$
......@@ -22,17 +22,14 @@
#include "TMSSBridge.h"
#include <boost/property_tree/json_parser.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/algorithm/string.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <curlpp/cURLpp.hpp>
#include <curl/curl.h>
#include <jsoncpp/json/json.h>
namespace pt = boost::property_tree;
using namespace std;
......@@ -43,10 +40,10 @@ namespace LOFAR {
// TMSSBridge Constructor
itsUser ("test"),
itsPassword ("test"),
itsHost (""), // just to start with maybe user and password need
itsPort (8000)
itsHost(""), // just to start with maybe user and password need
......@@ -71,7 +68,6 @@ vector<int> TMSSBridge::getSubTaskIDStartingInThreeMinutes(ptime currentTime, st
string queryStr = "/api/?start_time__lt=" + currentTimeStr + "&cluster__name==" + clusterName;
Json::Value result = httpGET(itsHost, itsPort, queryStr);
vector<string> urlList = translateHttpResultToSortedUrlList(result);
......@@ -83,38 +79,113 @@ vector<int> TMSSBridge::getSubTaskIDStartingInThreeMinutes(ptime currentTime, st
// json_response.get('count'))
// ... and results[idx].items('url)
// if multiple found sort on startTime !
vector<string> TMSSBridge::translateHttpResultToSortedUrlList(Json::Value jsonResult)
vector<string> TMSSBridge::translateHttpResultToSortedUrlList(Json::Value jsonRoot)
vector<string> urlList;
vector<string> urlList{};
// Read values
int nbrSubTasksFound = jsonResult["count"].asInt();
const int nbrTasksFound(jsonRoot["count"].asInt());
const Json::Value results = jsonRoot["results"];
for(int idx=0; idx<results.size(); ++idx) {
string urlStr = results[idx]["url"].asString();
string startTimeStr = results[idx]["start_time"].asString();
// Only interested in the subTaskID
boost::split(tmp, urlStr, boost::is_any_of("/subtask/"));
// TODO: I am lazy now....sort on ascending starttime
return urlList;
std::size_t callback(const char* in,
std::size_t size,
std::size_t num,
std::string* out)
const std::size_t totalBytes(size * num);
out->append(in, totalBytes);
return totalBytes;
// Performs an HTTP GET and return the response body
// Need to check respons status code of http (200)
// Inspired by
// Example:
// httpGET("", 8000, "/api/subtask/?start_time__lt=2020-03-04T12:03:00"
// results in a json string output
Json::Value TMSSBridge::httpGET(const string& host, const int port, const string& target)
// TODO Execute using curl stuff and endup with Json::Value
// Check for http result 200
Json::Value jsonResult("dummy");
return jsonResult;
Json::Value jsonData("");
const std::string url(host + target);
CURL* curl = curl_easy_init();
// Set remote URL.
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
// Don't bother trying IPv6, which would increase DNS resolution time.
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
// Don't wait forever, time out after 10 seconds.
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
// Follow HTTP redirects if necessary.
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
// Response information.
long httpCode(0);
std::unique_ptr<std::string> httpData(new std::string());
// Hook up data handling function.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
// Hook up data container (will be passed as the last parameter to the
// callback handling function). Can be any pointer type, since it will
// internally be passed as a void pointer.
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
// Run our HTTP GET command, capture the HTTP response code, and clean up.
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
if (httpCode == 200)
std::cout << "\nGot successful response from " << url << std::endl;
// Response looks good - done using Curl now. Try to parse the results
// and print them out.
Json::Reader jsonReader;
std::string httpResponse(*httpData.get());
if (jsonReader.parse(httpResponse, jsonData))
// TODO:
// How we deal with logging in Lofar C++ ?
// for now just do a stdout...
std::cout << "Successfully parsed JSON data" << std::endl;
std::cout << "\nJSON data received:" << std::endl;
std::cout << jsonData.toStyledString() << std::endl;
THROW(TMSSBridgeException, "Could not parse HTTP data as JSON. HTTP data was:\n" + httpResponse);
THROW(TMSSBridgeException, "Couldn't GET from " + url + " exiting with http code " + to_string(httpCode));
return jsonData;
......@@ -23,6 +23,8 @@
#include <Common/LofarTypes.h>
#include <Common/Exception.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <jsoncpp/json/json.h>
......@@ -43,22 +45,25 @@ public:
vector<int> getSubTaskIDStartingInThreeMinutes(ptime currentTime, string clusterName);
// Actually the next method is private, make it public to be able to use in UnitTest++
// Actually the next method are private, make it public to be able to use in UnitTest++
vector<string> translateHttpResultToSortedUrlList(Json::Value result);
// http request to TMSS
Json::Value httpGET(const string& host, int const port, const string& target);
// Copying is not allowed
TMSSBridge(const TMSSBridge&);
TMSSBridge& operator=(const TMSSBridge&);
// http request to TMSS
Json::Value httpGET(const string& host, int const port, const string& target);
string itsUser;
string itsPassword;
string itsHost;
int itsPort;
EXCEPTION_CLASS(TMSSBridgeException, LOFAR::Exception);
......@@ -27,7 +27,6 @@
#include <fstream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <jsonccp/json/json.h>
......@@ -38,6 +37,7 @@ using namespace boost::property_tree;
using namespace LOFAR::MainCU;
// Helper funtion to retrieve json data from a file
Json::Value readFile(const std::string& jsonFile)
ifstream ifs(jsonFile.c_str());
......@@ -54,15 +54,17 @@ Json::Value readFile(const std::string& jsonFile)
// Check if given json data (read from file) results ins correct output vector
// check if json read goes well as precondition for the test
// See jsoncpp
// Check if json read goes well as precondition for the test
Json::Value jsonData(readFile("test_response.json"));
int count = jsonData["count"];
// check if count is equal to 4 .... otherwise precond test did not match so will make no sense to continue
// Check if count is equal to 4, otherwise precondition of the test is not ok, so fail
CHECK_EQUAL(4, count);
std::cout << count;
TMSSBridge testTMSSBridge;
......@@ -74,18 +76,19 @@ TEST(tmss_translate_http_result_ok)
// An empty json file should result in an empty vector list
Json::Value jsonData("{}");
TMSSBridge testTMSSBridge;
// Read file json
std::vector<string> testResult;
testResult = testTMSSBridge.translateHttpResultToSortedUrlList(jsonData);
// Do some check like CHECK_EQUAL
int main(int, const char *[])
return UnitTest::RunAllTests();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment