How can I send a POST request in C ++ without using sockets - c++

I have python code that sends a POST request and gets a json, I need to rewrite it in C ++ (Windows 10, Visual Studio 2019). I don’t understand what tools can really do everything I need without complicating the code.
There will be a console application that must send a request to send or receive data, more precisely a video stream.
I read about Boost.Asio, but it seems to work only with sockets, is there any way without them? At first I wanted to use it, as the most famous. I read about сurl, but it hasn't been updated for a long time, is it still relevant?
headers_predict = {
"Content-type": "application/json;charset=UTF-8",
"Accept": "application/json",
"X-Session-ID": session_id
}
data_predict = {
"audio": {
"data": sound_base64,
"mime": "audio/pcm16"
},
"package_id": ""
}
url = 'https://cp.speechpro.com/recognize'
r = requests.post(url, headers=headers_predict,
data=json.dumps(data_predict))
print('Response: %s' % r.text)
I wouldn't want to use sockets, because I don't understand them.
I need to be able to set the header and data as a json.

sockets, is there any way without them?
Technically, HTTP does not specify the underlying transport protocol and it can work with any sort of streaming transport. You could for example write the request into a file.
But, if you currently use TCP and don't want to change that, then you must use sockets. You don't need to interact with them directly if you use an existing HTTP client library.

Related

C++ Boost http post request [duplicate]

I've to use a C++ library for sending data to a REST-Webservice of our company.
I start with Boost and Beast and with the example given here under Code::Blocks in a Ubuntu 16.04 enviroment.
The documentation doesn't helped me in following problem:
My code is, more or less, equal to the example and I can compile and send a GET-request to my test webservice successfully.
But how can I set data inside the request (req) from this definition:
:
beast::http::request<beast::http::string_body> req;
req.method("GET");
req.target("/");
:
I tried to use some req.body.???, but code completition doesn't give me a hint about functionality (btw. don't work). I know that req.method must be changed to "POST" to send data.
Google doesn't show new example about this, only the above code is found as a example.
Someone with a hint to a code example or using about the Beast (roar). Or should I use websockets? Or only boost::asio like answered here?
Thanks in advance and excuse my bad english.
Small addition to Eliott Paris's answer:
Correct syntax for setting body is
req.body() = "name=foo";
You should add
req.prepare_payload();
after setting the body to set body size in HTTP headers.
To send data with your request you'll need to fill the body and specify the content type.
beast::http::request<beast::http::string_body> req;
req.method(beast::http::verb::post);
req.target("/");
If you want to send "key=value" as a "x-www-form-urlencoded" pair:
req.set(beast::http::field::content_type, "application/x-www-form-urlencoded");
req.body() = "name=foo";
Or raw data:
req.set(beast::http::field::content_type, "text/plain");
req.body() = "Some raw data";

How do we read headers from boost websocket servers in C++

Ive been trying to write a server for a client that uses websockets.
Currently the client code is similar to :
ws.async_handshake_ex(handshake_response,hostname,"/",
[this](websocket::request_type& request) {
request.set("header1","value1");
request.set("header2","value2");
},
function_after_handshake());
Now, on my server side I've been trying to use these values of headers. I've been trying to write code like so :
ws.async_accept_ex(
[this](websocket::response_type& res) {
cout<<res.base().get("header1");
},
function_after_handshake_server());
Obviously this is wrong, but what would be the correct way to do this on server side?
I cannot change client code(totally not mine), and thus can't use latest versions of boost.

Apache Thrift for just processing, not server

I hope I don't have misunderstood the Thrift concept, but what I see from (example) questions like this, this framework is composed by different modular layers that can be enabled or disabled.
I'm mostly interesed in the "IDL part" of Thrift, so that I can create a common interface between my C++ code and an external Javascript application. I would like to call C++ functions using JS, with Binary data transmission, and I've already used the compiler for this.
But both my C++ (the server) and JS (client) application already exchange data using a C++ Webserver with Websockets support, it is not provided by Thrift.
So I was thinking to setup the following items:
In JS (already done):
TWebSocketTransport to send data to my "Websocket server" (with host ws://xxx.xxx.xxx.xxx)
TBinaryProtocol to encapsulate the data (using this JS implementation)
The compiled Thrift JS library with the correspondent C++ functions to call (done with the JS compiler)
In C++ (partial):
TBinaryProtocol to encode/decode the data
A TProcessor with handler to get the data from the client and process it
For now, the client is already able to sent requests to my websocket server, I see receiving them in binary form and I just need Thrift to:
Decode the input
Call the appropriate C++ function
Encode the output
My webserver will send the response to the client. So no "Thrift server" is needed here. I see there is the TProcessor->process() function, I'm trying to use it when I receive the binary data but it needs an in/out TProtocol. No problem here... but in order to create the TBinaryProtocol I also need a TTransport! If no Thrift server is expected... what Transport should I use?
I tried to set TTransport to NULL in TBinaryProtocol constructor, but once I use it it gives nullptr exception.
Code is something like:
Init:
boost::shared_ptr<MySDKServiceHandler> handler(new MySDKServiceHandler());
thriftCommandProcessor = boost::shared_ptr<TProcessor>(new MySDKServiceProcessor(handler));
thriftInputProtocol = boost::shared_ptr<TBinaryProtocol>(new TBinaryProtocol(TTransport???));
thriftOutputProtocol = boost::shared_ptr<TBinaryProtocol>(new TBinaryProtocol(TTransport???));
When data arrives:
this->thriftInputProtocol->writeBinary(input); // exception here
this->thriftCommandProcessor->process(this->thriftInputProtocol, this->thriftOutputProtocol, NULL);
this->thriftOutputProtocol->readBinary(output);
I've managed to do it using the following components:
// create the Processor using my compiled Thrift class (from IDL)
boost::shared_ptr<MySDKServiceHandler> handler(new MySDKServiceHandler());
thriftCommandProcessor = boost::shared_ptr<TProcessor>(new ThriftSDKServiceProcessor(handler));
// Transport is needed, I use the TMemoryBuffer so everything is kept in local memory
boost::shared_ptr<TTransport> transport(new apache::thrift::transport::TMemoryBuffer());
// my client/server data is based on binary protocol. I pass the transport to it
thriftProtocol = boost::shared_ptr<TProtocol>(new TBinaryProtocol(transport, 0, 0, false, false));
/* .... when the message arrives through my webserver */
void parseMessage(const byte* input, const int input_size, byte*& output, int& output_size)
{
// get the transports to write and read Thrift data
boost::shared_ptr<TTransport> iTr = this->thriftProtocol->getInputTransport();
boost::shared_ptr<TTransport> oTr = this->thriftProtocol->getOutputTransport();
// "transmit" my data to Thrift
iTr->write(input, input_size);
iTr->flush();
// make the Thrift work using the Processor
this->thriftCommandProcessor->process(this->thriftProtocol, NULL);
// the output transport (oTr) contains the called procedure result
output = new byte[MAX_SDK_WS_REPLYSIZE];
output_size = oTr->read(output, MAX_SDK_WS_REPLYSIZE);
}
My webserver will send the response to the client. So no "Thrift server" is needed here. I see there is the TProcessor->process() function, I'm trying to use it when I receive the binary data but it needs an in/out TProtocol. No problem here... but in order to create the TBinaryProtocol I also need a TTransport! If no Thrift server is expected... what Transport should I use?
The usual pattern is to store the bits somewhere and use that buffer or data stream as the input, same for the output. For certain languages there is a TStreamTransport available, for C++ the TBufferBase class looks promising to me.

Qt HTTP request sending DELETE with Data

rest API:
someting/post expects 'token' as bytearray body data
something/delete expects 'token' as bytearray body data
Using Qt I can prepare the data in a QByteArray and send via deleteResource (that doesn't accepts a data parameter) and I can use sendCustomRequest that accepts a data parameter, but if I use the later with DELETE I have no data.
With POST, I do have the data.
Minimal code example, python server - just to exemplify. the Qt code is below.:
#route('/something/delete', "DELETE")
def somethingDelete(url, post):
print(post) # empty
#route('/something/delete2', "POST")
def somethingDelete2(url, post):
print(post) # correct output.
and the Qt code that triggers the server calls - This code is higly shortened to simplify, but the idea is that.
QNetworkRequest req;
req.setRawHeader("OCS-APIREQUEST", "true");
req.setUrl = Utility::concatUrlPath(account()->url(), path());
QByteArray bufferData("token=" + _token);
sendCustomRequest(req, "POST", bufferData);
as soon as I change the POST to DELETE, I don't get the token, but the correct python function is executed.
The DELETE HTTP verb does not have a request body so your buffer is probably simply dropped by Qt. To use DELETE you would need to encode your token in the URL.
As of Qt 5.9.2, it seems that Qt might ignore body data when performing a DELETE operation.
In Qt code in QNetworkReplyHttpImplPrivate::postRequest(), one can see that createUploadByteDevice() is not called when the operation is QNetworkAccessManager::DeleteOperation.
However, this is only valid when the DELETE request is sent by calling QNetworkAccessManager::deleteResource(), which is the only way to create a network request with the QNetworkAccessManager::DeleteOperation operation. Also note that this function does not allow you to send any body data.
If you use QNetworkAccessManager::sendCustomRequest() to send the request, then as far as Qt is concerned the operation is QNetworkAccessManager::CustomOperation. The custom verb you pass is not processed further, and Qt will behave exactly the same whatever the value of verb is. Even if verb is a known value like POST or DELETE.
This means that Qt does not discard the body data.
So if you used QNetworkAccessManager::sendCustomRequest(), as you claim, your body data is sent to the server (confirmed by Wireshark). So the issue is not on Qt side, but on the server side.

Growl Notifications from a Web Server

I notice that Growl allows for the possibility of Growl notifications from a website. Has anyone tried implementing this?
If so, what form did it take? Did you implement multi user support? And, can you provide any code examples (C# or Objective-C would preferable but I'm not that fussed)?
Rich
There are GNTP (Growl Network Transport Protocol) bindings for various languages, a list of bindings can be found here - these allow you to send notifications from, say, a PHP script.
I wouldn't trust Growl's UDP system directly, but rather write a server that receives and stores notifications (maybe as a tiny web app), and a local script that routinely grabs any new messages via HTTP and Growls them. Not complicated at all, will be more reliable than UDP, and can queue up messages when your Growl'ing machine is powered-off or unreachable. Shouldn't take long to implement
Basically, server.php in pseudo-PHP (which could use Net_Growl):
<?php
if($_GET['action'] == "store"){
$title = $_POST['title'];
$message = $_POST['message'];
$password = sha1($_POST['password']);
if($password == "..."){
store_in_database(sanitise($title), sanitise($message);
}
} else {
print(json_encode(get_notifications_from_database()));
mark_notifications_as_read();
}
?>
client.py in pseudo-Python (which could use gntp):
while 1:
time.sleep(60):
data = urllib.urlopen("http://myserver.com/server.php?action=get&password=blah").read()
for line in data:
notif = json.decode(line)
growl.alert(notif['title'], notif['message'])