-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
jsonwebclient.cpp
117 lines (100 loc) · 4.25 KB
/
jsonwebclient.cpp
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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
110
111
112
113
114
// SPDX-License-Identifier: GPL-3.0-or-later
//
// Copyright (c) 2013-2023 plan44.ch / Lukas Zeller, Zurich, Switzerland
//
// Author: Lukas Zeller <[email protected]>
//
// This file is part of p44utils.
//
// p44utils 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.
//
// p44utils 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 p44utils. If not, see <http://www.gnu.org/licenses/>.
//
#include "jsonwebclient.hpp"
using namespace p44;
JsonWebClient::JsonWebClient(MainLoop &aMainLoop) :
HttpComm(aMainLoop)
{
}
JsonWebClient::~JsonWebClient()
{
}
void JsonWebClient::requestThreadSignal(ChildThreadWrapper &aChildThread, ThreadSignals aSignalCode)
{
if (jsonResponseCallback) {
// only if we have a json callback, we need to parse the response at all
if (aSignalCode==threadSignalCompleted) {
requestInProgress = false; // thread completed
JsonObjectPtr message;
if (Error::isOK(requestError) || requestError->isDomain(WebError::domain())) {
// try to decode JSON
struct json_tokener* tokener = json_tokener_new();
struct json_object *o = json_tokener_parse_ex(tokener, response.c_str(), (int)response.size());
if (o==NULL) {
// error (or incomplete JSON, which is fine)
JsonError::ErrorCodes err = json_tokener_get_error(tokener);
if (err!=json_tokener_continue) {
// real JSON error - however, if we already have a http level error, just annotate
if (Error::notOK(requestError))
requestError->prefixMessage("JSON cannot be decoded, probably due to: ");
else
requestError = ErrorPtr(new JsonError(err));
}
}
else {
// got JSON object
message = JsonObject::newObj(o);
}
json_tokener_free(tokener);
}
// call back with result of request
LOG(LOG_DEBUG, "JsonWebClient: <- received JSON response (Error=%s), answer:\n%s", Error::text(requestError), JsonObject::text(message));
// Note: this callback might initiate another request already
if (jsonResponseCallback) {
// use this callback, but as callback routine might post another request immediately, we need to free the member first
JsonWebClientCB cb = jsonResponseCallback;
jsonResponseCallback.clear();
cb(message, requestError);
}
// release child thread object now
childThread.reset();
}
else {
// none of the signals we understand at this level (e.g. httpThreadSignalDataReady), let inherited handle that
inherited::requestThreadSignal(aChildThread, aSignalCode);
}
}
else {
// no JSON callback, let inherited handle this
inherited::requestThreadSignal(aChildThread, aSignalCode);
}
}
bool JsonWebClient::jsonRequest(const char *aURL, JsonWebClientCB aResponseCallback, const char *aMethod, JsonObjectPtr aJsonRequest, const char* aContentType, bool aSaveHeaders)
{
// set callback
jsonResponseCallback = aResponseCallback;
// encode JSON, if any
string jsonstring;
if (aJsonRequest) {
jsonstring = aJsonRequest->json_c_str();
}
LOG(LOG_DEBUG, "JsonWebClient: -> sending %s JSON request to %s:\n%s", aMethod, aURL, jsonstring.c_str());
return httpRequest(aURL, NoOP, aMethod, jsonstring.c_str(), aContentType, -1, aSaveHeaders);
}
bool JsonWebClient::jsonReturningRequest(const char *aURL, JsonWebClientCB aResponseCallback, const char *aMethod, const string &aPostData, const char* aContentType, bool aSaveHeaders)
{
if (!aContentType) aContentType = CONTENT_TYPE_FORMDATA;
// set callback
jsonResponseCallback = aResponseCallback;
LOG(LOG_DEBUG, "JsonWebClient: -> sending %s raw data request to %s:\n%s", aMethod, aURL, aPostData.c_str());
return httpRequest(aURL, NoOP, aMethod, aPostData.c_str(), aContentType, -1, aSaveHeaders);
}