C++ - how to send a HTTP post request using Curlpp or libcurl - c++

I would like to send an http post request in c++. It seems like libcurl (Curlpp) is the way to go.
Now, here is a typical request that am sending
http://abc.com:3456/handler1/start?<name-Value pairs>
The name values pairs will have:
field1: ABC
field2: b, c, d, e, f
field3: XYZ
etc.
Now, I would like to know how to achieve the same using curlpp or libcurl.
Code snippets will really help.

Don't have experience with Curlpp but this is how I did it with libcurl.
You can set your target url using
curl_easy_setopt(m_CurlPtr, CURLOPT_URL, "http://urlhere.com/");
POST values are stored in a linked list -- you should have two variables to hold the begin and the end of that list so that cURL can add a value to it.
struct curl_httppost* beginPostList;
struct curl_httppost* endPostList;
You can then add this post variable using
curl_formadd(&beginPostList, &endPostList, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
Submitting then works like this
curl_easy_setopt(m_CurlPtr, CURLOPT_POST, true);
curl_easy_setopt(m_CurlPtr, CURLOPT_HTTPPOST, beginPostList);
curl_easy_perform(m_CurlPtr);
Hope this helps!

Related

Regular Expression in put request [duplicate]

This question already has answers here:
Safely turning a JSON string into an object
(28 answers)
Closed 7 years ago.
I want to parse a JSON string in JavaScript. The response is something like
var response = '{"result":true,"count":1}';
How can I get the values result and count from this?
The standard way to parse JSON in JavaScript is JSON.parse()
The JSON API was introduced with ES5 (2011) and has since been implemented in >99% of browsers by market share, and Node.js. Its usage is simple:
const json = '{ "fruit": "pineapple", "fingers": 10 }';
const obj = JSON.parse(json);
console.log(obj.fruit, obj.fingers);
The only time you won't be able to use JSON.parse() is if you are programming for an ancient browser, such as IE 7 (2006), IE 6 (2001), Firefox 3 (2008), Safari 3.x (2009), etc. Alternatively, you may be in an esoteric JavaScript environment that doesn't include the standard APIs. In these cases, use json2.js, the reference implementation of JSON written by Douglas Crockford, the inventor of JSON. That library will provide an implementation of JSON.parse().
When processing extremely large JSON files, JSON.parse() may choke because of its synchronous nature and design. To resolve this, the JSON website recommends third-party libraries such as Oboe.js and clarinet, which provide streaming JSON parsing.
jQuery once had a $.parseJSON() function, but it was deprecated with jQuery 3.0. In any case, for a long time, it was nothing more than a wrapper around JSON.parse().
WARNING!
This answer stems from an ancient era of JavaScript programming during which there was no builtin way to parse JSON. The advice given here is no longer applicable and probably dangerous. From a modern perspective, parsing JSON by involving jQuery or calling eval() is nonsense. Unless you need to support IE 7 or Firefox 3.0, the correct way to parse JSON is JSON.parse().
First of all, you have to make sure that the JSON code is valid.
After that, I would recommend using a JavaScript library such as jQuery or Prototype if you can because these things are handled well in those libraries.
On the other hand, if you don't want to use a library and you can vouch for the validity of the JSON object, I would simply wrap the string in an anonymous function and use the eval function.
This is not recommended if you are getting the JSON object from another source that isn't absolutely trusted because the eval function allows for renegade code if you will.
Here is an example of using the eval function:
var strJSON = '{"result":true,"count":1}';
var objJSON = eval("(function(){return " + strJSON + ";})()");
alert(objJSON.result);
alert(objJSON.count);
If you control what browser is being used or you are not worried people with an older browser, you can always use the JSON.parse method.
This is really the ideal solution for the future.
If you are getting this from an outside site it might be helpful to use jQuery's getJSON. If it's a list you can iterate through it with $.each
$.getJSON(url, function (json) {
alert(json.result);
$.each(json.list, function (i, fb) {
alert(fb.result);
});
});
If you want to use JSON 3 for older browsers, you can load it conditionally with:
<script>
window.JSON ||
document.write('<script src="//cdnjs.cloudflare.com/ajax/libs/json3/3.2.4/json3.min.js"><\/scr'+'ipt>');
</script>
Now the standard window.JSON object is available to you no matter what browser a client is running.
The following example will make it clear:
let contactJSON = '{"name":"John Doe","age":"11"}';
let contact = JSON.parse(contactJSON);
console.log(contact.name + ", " + contact.age);
// Output: John Doe, 11
If you pass a string variable (a well-formed JSON string) to JSON.parse from MVC #Viewbag that has doublequote, '"', as quotes, you need to process it before JSON.parse (jsonstring)
var jsonstring = '#ViewBag.jsonstring';
jsonstring = jsonstring.replace(/"/g, '"');
You can either use the eval function as in some other answers. (Don't forget the extra braces.) You will know why when you dig deeper), or simply use the jQuery function parseJSON:
var response = '{"result":true , "count":1}';
var parsedJSON = $.parseJSON(response);
OR
You can use this below code.
var response = '{"result":true , "count":1}';
var jsonObject = JSON.parse(response);
And you can access the fields using jsonObject.result and jsonObject.count.
Update:
If your output is undefined then you need to follow THIS answer. Maybe your json string has an array format. You need to access the json object properties like this
var response = '[{"result":true , "count":1}]'; // <~ Array with [] tag
var jsonObject = JSON.parse(response);
console.log(jsonObject[0].result); //Output true
console.log(jsonObject[0].count); //Output 1
The easiest way using parse() method:
var response = '{"a":true,"b":1}';
var JsonObject= JSON.parse(response);
this is an example of how to get values:
var myResponseResult = JsonObject.a;
var myResponseCount = JsonObject.b;
JSON.parse() converts any JSON String passed into the function, to a JSON object.
For better understanding, press F12 to open the Inspect Element of your browser, and go to the console to write the following commands:
var response = '{"result":true,"count":1}'; // Sample JSON object (string form)
JSON.parse(response); // Converts passed string to a JSON object.
Now run the command:
console.log(JSON.parse(response));
You'll get output as Object {result: true, count: 1}.
In order to use that object, you can assign it to the variable, let's say obj:
var obj = JSON.parse(response);
Now by using obj and the dot(.) operator you can access properties of the JSON Object.
Try to run the command
console.log(obj.result);
Without using a library you can use eval - the only time you should use. It's safer to use a library though.
eg...
var response = '{"result":true , "count":1}';
var parsedJSON = eval('('+response+')');
var result=parsedJSON.result;
var count=parsedJSON.count;
alert('result:'+result+' count:'+count);
If you like
var response = '{"result":true,"count":1}';
var JsonObject= JSON.parse(response);
you can access the JSON elements by JsonObject with (.) dot:
JsonObject.result;
JsonObject.count;
I thought JSON.parse(myObject) would work. But depending on the browsers, it might be worth using eval('('+myObject+')'). The only issue I can recommend watching out for is the multi-level list in JSON.
An easy way to do it:
var data = '{"result":true,"count":1}';
var json = eval("[" +data+ "]")[0]; // ;)
If you use Dojo Toolkit:
require(["dojo/json"], function(JSON){
JSON.parse('{"hello":"world"}', true);
});
As mentioned by numerous others, most browsers support JSON.parse and JSON.stringify.
Now, I'd also like to add that if you are using AngularJS (which I highly recommend), then it also provides the functionality that you require:
var myJson = '{"result": true, "count": 1}';
var obj = angular.fromJson(myJson);//equivalent to JSON.parse(myJson)
var backToJson = angular.toJson(obj);//equivalent to JSON.stringify(obj)
I just wanted to add the stuff about AngularJS to provide another option. NOTE that AngularJS doesn't officially support Internet Explorer 8 (and older versions, for that matter), though through experience most of the stuff seems to work pretty well.
If you use jQuery, it is simple:
var response = '{"result":true,"count":1}';
var obj = $.parseJSON(response);
alert(obj.result); //true
alert(obj.count); //1

PowerBI Query WebMethod.Post returns Expression.Error: We cannot convert the value "POST" to type Function

I'm using a website that requires that their API key AND query data be submitted using Webform.Post method. I'm able to get this to work in Python, C# and I'm even able to construct and execute a cURL command which returns a usable JSON file that Excel can parse. I am also using Postman to validate my parameters and everything looks good using all these methods. However, my goal is to build a query form that I can use within Excel but I can't get past this query syntax in PowerBi Query.
For now I am doing a simple query. That query looks like this:
let
url_1 = "https://api.[SomeWebSite].com/api/v1.0/search/keyword?apiKey=blah-blah-blah",
Body_1 = {
"SearchByKeywordRequest:
{
""keyword"": ""Hex Nuts"",
""records"": 0,
""startingRecord"": 0,
""searchOptions"": Null.Type,
""searchWithYourSignUpLanguage"": Null.Type
}"
},
Source = WebMethod.Post(url_1,Body_1)
in
Source
ScreenSnip showing valid syntax
It generates the following error:
Expression.Error: We cannot convert the value "POST" to type Function.
Details:
Value=POST
Type=[Type]
ScreenSnip of Error as it appears in PowerQuery Advanced Editor
I've spend the better part of the last two days trying to find either some example using this method or documentation. The Microsoft documentation simple states the follow:
WebMethod.Post
04/15/2018
2 minutes to read
About
Specifies the POST method for HTTP.
https://learn.microsoft.com/en-us/powerquery-m/webmethod-post
This is of no help and the only posts I have found so far criticize the poster for not using GET versus POST. I would do this but it is NOT supported by the website I'm using. If someone could just please either point me to a document which explains what I am doing wrong or suggest a solution, I would be grateful.
WebMethod.Post is not a function. It is a constant text value "POST". You can send POST request with either Web.Contents or WebAction.Request function.
A simple example that posts JSON and receives JSON:
let
url = "https://example.com/api/v1.0/some-resource-path",
headers = [#"Content-Type" = "application/json"],
body = Json.FromValue([Foo = 123]),
source = Json.Document(Web.Contents(url, [Headers = headers, Content = body])),
...
Added Nov 14, 19
Request body needs to be a binary type, and included as Content field of the second parameter of Web.Contents function.
You can construct a binary JSON value using Json.FromValue function. Conversely, you can convert a binary JSON value to a corresponding M type using Json.Document function.
Note {} is list type in M language, which is similar to JSON array. [] is record type, which is similar to JSON object.
With that said, your query should be something like this,
let
url_1 = "https://api.[SomeWebSite].com/api/v1.0/search/keyword?apiKey=blah-blah-blah",
Body_1 = Json.FromValue([
SearchByKeywordRequest = [
keyword = "Hex Nuts",
records = 0,
startingRecord = 0,
searchOptions = null,
searchWithYourSignUpLanguage = null
]
]),
headers = [#"Content-Type" = "application/json"],
source = Json.Document(Web.Contents(url_1, [Headers = headers, Content = Body_1])),
...
References:
Web.Contents (https://learn.microsoft.com/en-us/powerquery-m/web-contents)
Json.FromValue (https://learn.microsoft.com/en-us/powerquery-m/json-fromvalue)
Json.Document (https://learn.microsoft.com/en-us/powerquery-m/json-document)

How do I create HTTP request with some parameters by POCO?

I'm a new User of POCO and could get HTTP response after HTTP::Request.
By the way, How do I create HTTP request with some parameters? For example, I want to set URI, http://xxxx/index.html?name=hoge&id=fuga&data=foo.
Of course I know it's possible if I set this uri directly. But I want to realize this like below. Does anyone know this way?
URI uri("http://xxx/index.html");
uri.setParam("name", "hoge");
uri.setParam("id", "fuga");
uri.setParam("data", "foo");
If you had looked up the documentation for Poco::URI, you'd see it's done with uri.addQueryParameter("name", "value"):
void addQueryParameter(
const std::string & param,
const std::string & val = ""
);
Adds "param=val" to the query; "param" may not be empty. If val is empty, only '=' is appended to the parameter.
In addition to regular encoding, function also encodes '&' and '=', if found in param or val.
You can also set all the parameters with setQueryParameters.
Unfortunately, Poco doesn't let you set the value of an existing query parameter (or remove it). If you want to do that, you have to clear the query portion of the URI and readd all the parameters you want with their values.

Springs RestTemplate doesn't find the right MessageConverter when reciving data from the IMDB api

first I have to say, that I am pretty new to Springs RestTemplate.
I am trying to receive data from the imdb-api. (For example http://imdbapi.org/?title=Avatar&type=xml) Therefore I am using Springs RestTemplate.
But:
the webservice returns the data as application/octet-stream (even I declared that I want it as xml (when I browse the site with my browser I get the data as text/xml))
RestTemplate doesn't find my declared ByteArrayMessageConverter (to convert application/octet-stream)
I realy don't know where my mistakes are.
Here is the code to initialise the restTemplate:
public void onInit() {
_log.debug("Setting up the Spring Resttemplate");
_restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new SourceHttpMessageConverter<Source>());
list.add(new ByteArrayHttpMessageConverter());
_restTemplate.setMessageConverters(list);
_log.debug("Setting up the HTTP Headers for Restrequest");
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
_log.trace("allow {}", MediaType.APPLICATION_XML_VALUE);
acceptableMediaTypes.add(MediaType.APPLICATION_XML);
_log.trace("allow {}", MediaType.TEXT_HTML_VALUE);
acceptableMediaTypes.add(MediaType.TEXT_XML);
_log.trace("set accepted charset to uft-8");
List<Charset> acceptableCharsets = new ArrayList<Charset>();
acceptableCharsets.add(Charset.forName("utf-8"));
_httpHeaders = new HttpHeaders();
_httpHeaders.set("User-Agent", "something"); //only a user-agent, because the api returns a 403 if it is not set
_httpHeaders.setAcceptCharset(acceptableCharsets);
_httpHeaders.setAccept(acceptableMediaTypes);
}
Here is the code with the call:
_log.info("connect to Imdb-Webservice {}", _imbdWebserviceBaseUrl);
Map<String, Object> uriVariables = new HashMap<String, Object>();
uriVariables.put("title", pTitle);
ResponseEntity<Source> response = _restTemplate.exchange(_imbdWebserviceBaseUrl, HttpMethod.GET, new HttpEntity<String>(_httpHeaders), Source.class, uriVariables);
_imbdWebserviceBaseUrl is set to http://imdbapi.org/?title={title}&type=xml
Then I am getting this error message:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [interface javax.xml.transform.Source] and content type [application/octet-stream]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:107)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:687)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:673)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:491)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:454)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:401)
at my.domain.projectname.integrationimpl.WebserviceHelper.getXml(WebserviceHelper.java:131)
Thanks for your help
the web service returns the data as application/octet-stream (even I declared that I want it as xml (when I browse the site with my browser I get the data as text/xml))
As far as I can see this rest service is not giving back the correct Content-Type (text/xml or similar). If your browser renders it correctly that's probably Chrome or Firefox, but IE will just show you html-ish kind of output.
RestTemplate doesn't find my declared ByteArrayMessageConverter (to convert application/octet-stream)
Well you are asking for a Source as far as I can see:
ResponseEntity<Source> response = _restTemplate.exchange(_imbdWebserviceBaseUrl, HttpMethod.GET, new HttpEntity<String>(_httpHeaders), Source.class, uriVariables);
The MessageConverters themselves have a method that determines if this converter is applicable, for ByteArrayHttpMessageConverter this is:
#Override
public boolean supports(Class<?> clazz) {
return byte[].class.equals(clazz);
}
Since you are asking for a Source.class it wont use this converter.

Qt QNetworkAccessManager or other method get html status code without getting page contenet?

i need to get web sites html status codes
today i just do simple get request to the domain , and then i get the status code as part of the response , but also the site index.html content .
pNetworkManager = new QNetworkAccessManager(this);
reply = pNetworkManager->get(request);
QVariant vStatusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
data=reply->readAll();
this last function i like to avoid if it can be avoided ,
is there any way to get only the domain status code ?
Maybe you can send a HEAD request instead of a GET request?
This is not a Qt / client specific solution, but is the approach recommended by the HTTP protocol when you don't need the content, but just want to get the headers that a request would normally produce, for example in order to validate that the page exists.
I suppose this could be done with QNetworkAccessManager using the head() method
I agree with #shevron's answer, but if the site you're communicating with isn't "clever" enough to implement the HEAD request, you can still avoid the readAll() call.
QByteArray line = reply->readLine(); //< eg "HTTP/1.0 200 OK"
QList<QByteArray> chunks = line.split(' ');
QString statusCode = chunks[1];
That should avoid the memory overhead of readAll().