I am using Poco to send HTTP requests, as the name implies. Right now, I'm just trying to send a GET request to google.com and store the resulting HTML in a string to test out Poco and see if it fits what I need. However, I'm having a little trouble with this. Here's my code:
try
{
Poco::URI uri("https://www.google.com");
std::string path(uri.getPathAndQuery());
if (path.empty()) path = "/";
Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort());
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, path, Poco::Net::HTTPMessage::HTTP_1_1);
request.add("Content-Length", "0");
Poco::Net::HTTPResponse response;
doRequest(session, request, response);
}
catch (Poco::Exception& exc)
{
OutputDebugStringA(exc.displayText().c_str());
}
void doRequest(Poco::Net::HTTPSClientSession& session, Poco::Net::HTTPRequest& request, Poco::Net::HTTPResponse& response)
{
session.sendRequest(request);
std::istream& is = session.receiveResponse(response);
std::string body(std::istreambuf_iterator<char>(is), { });
message = (LPCWSTR)response.getStatus();
}
I have put breakpoints on every line of doRequest, but the only ones that are triggered are the first two. After clicking continue on the second, the program simply continues as normal. I'm not getting any exceptions or anything. I am adding Content-Length: 0 to avoid a NoMessageException from Poco.
Related
In my application I want to stream jpg images through a HTTP web server using the POCO library, and for this I am using multipart/x-mixed-replace content type in my response body. This means when a GET request arrives to the HTTP server, it is continously sending images to the client in parts in a single http response.
The stream should close and the request handler should return when the client closes the window. But my problem with the HTTPServerResponse.send() stream is that it only gets destroyed, when the response object is destroyed, so I do not know when the client has left, and when do I have to stop sending the images.
That is how the code looks like:
#pragma once
#include <fstream>
#include <sstream>
#include <string>
#include "Poco/Net/HTTPRequestHandler.h"
class StreamHandler : public Poco::Net::HTTPRequestHandler {
public:
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override {
std::ifstream imgFile("../../assets/imgs/random.jpg");
std::stringstream ss{};
ss << imgFile.rdbuf();
std::string buf = ss.str();
std::string boundary = "--BOUNDARY--";
response.setVersion(request.getVersion());
response.setStatus(Poco::Net::HTTPServerResponse::HTTP_OK);
response.setChunkedTransferEncoding(false);
response.setKeepAlive(false);
response.setContentType("multipart/x-mixed-replace; boundary=" + boundary);
response.set("Access-Control-Allow-Origin", "*");
response.set("Connection", "Close");
response.set("Cache-Control",
"no-cache, no-store, must-revalidate, pre-check=0, post-check=0, max-age=0, false");
response.set("Pragma", "no-cache");
std::ostream& ostr = response.send();
while (true) { // <-- What is the stop condition?
ostr << boundary << "\r\n";
ostr << "Content-Type: image/jpeg\r\n"
"Content-Length: " +
std::to_string(buf.length()) + "\r\n\r\n";
ostr << buf;
ostr << "\r\n";
}
}
};
Is there a way to detect whether the client has left?
PS: Possibly I would like a solution within the boundaries of Poco::Net::HTTPRequestHandler. I do not want any solution that requires opening another port, or using another third party library only for the streaming. For example, I am already using nadjieb/cpp-mjpeg-streamer which is working great, but I want to simplify my code and depend only on POCO. In lower level libraries I saw good implementations that are using the following strategy:
while (true) {
if (res) {
res = http_res_send_chunk(req, part_buf, part_len);
} else {
break;
}
}
The send command returns with some positive integer in case of success, and with 0 if the send function failed. However, I cannot replicate this with POCO unfortunately. Any ideas how to get around this?
I finally found a solution and posted it here. If my answer gets accepted, I will flag this question as a duplicate.
I am new to the Boost library. I try to create an Rest HTTP request using the Boost::http library.
My question is how can i simply assign the JSON payload to the http request.
the following code snippet shows my current try which connects successfully but the payload is not assigned.
http::request<http::string_body> req{ http::verb::post, LOGIN_PATH, 10 };
req.set(beast::http::field::content_type, "application/json");
req.body() = std::move(serviceUser);
// Send the HTTP request to the remote host
http::write(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::dynamic_body> res;
// Receive the HTTP response
http::read(stream, buffer, res);
// Write the message to standard out
std::cout << res << std::endl;
return "OK";
The following snippet shows the JSON message.
std::stringstream strStream;
strStream << "{\"userName\" : lena, \"password\" : liebe }";
serviceUser = strStream.str();
Can you give me a simple example please. Importent to mention is that i use the Boost library version 1.70.
I have a problem with websocket connection to wss://www.bitmex.com/realtime.
I found an axample in this question: Connect Websocket with Poco libraries , but I can't do the same with my wss:// address.
HTTPClientSession cs("wss://www.bitmex.com", 443);
HTTPRequest request(HTTPRequest::HTTP_CONNECT, "/realtime", HTTPMessage::HTTP_1_1);
request.set("origin", "wss://www.bitmex.com");
HTTPResponse response;
try {
WebSocket* m_psock = new WebSocket(cs, request, response);
//some code
}
catch (std::exception &e) {
std::cout << "Exception " << e.what();
}
I'm always receiving the exception: "Host not found" after string
WebSocket* m_psock = new WebSocket(cs, request, response);
HTTPClientSession takes a host string as the first param but you have given a host string with a protocol on the front.
The samples have a WebSocketServer in Net but sometimes you need to look at the test suite to find more details and it does require a little more work.
See WebSocketTest.cpp for a basic test that uses a WebSocket.
I'm just starting with RESTful programming and trying to make a program in c++ using the Casablanca sdk (https://github.com/Microsoft/cpprestsdk). I know that I need to use GET, POST, PUT and DEL methods to do data transfer etc. But I cant seem to find any examples on how to do this. I currently need to send an integer value to the server from the client and get a Boolean response from the server. I cant find any good examples in Casablanca's documentation or the web. Any help regarding how to do this simple transfer would be appreciated.
Spending more time to explore the documentation and various examples on the internet would probably have got you the answer.
Basically, you have to set up a http listener, as the server, that will listen to client request at a particular url.
Then a client can send data on that url, to communicate with it.
Nevertheless, if you want to exchange data in json format,
Server would look something like this
void handle_post(http_request request)
{
json::value temp;
request.extract_json() //extracts the request content into a json
.then([&temp](pplx::task<json::value> task)
{
temp = task.get();
})
.wait();
//do whatever you want with 'temp' here
request.reply(status_codes::OK, temp); //send the reply as a json.
}
int main()
{
http_listener listener(L"http://localhost/restdemo"); //define a listener on this url.
listener.support(methods::POST, handle_post); //'handle_post' is the function this listener will go to when it receives a POST request.
try
{
listener
.open() //start listening
.then([&listener](){TRACE(L"\nstarting to listen\n");})
.wait();
while (true);
}
catch (exception const & e)
{
wcout << e.what() << endl;
}
}
Client would be,
int main()
{
json::value client_temp;
http_client client(L"http://localhost");
//insert data into the json e.g : json::value(54)
client.request(methods::POST, L"/restdemo", object)
.then([](http_response response)
{
if (response.status_code() == status_codes::OK)
{
return response.extract_json();
}
return pplx::task_from_result(json::value());
})
.then([&client_temp ](pplx::task<json::value> previousTask)
{
client_temp = previousTask.get();
})
.wait();
}
Your server reply will be stored into 'client_temp'
Hi I am uploading a file using multipart upload in POCO (by sending a the content of file appended with boundaries through a normal POST request). But when I try to read the response as:
std::ostream& myOStream = session.sendRequest(req);
// sends the body
myOStream << reqBody;
Poco::Net::HTTPResponse res;
// get the response body from server
std::istream& inStream = session.receiveResponse(res);
std::ostringstream outStringStream;
outStringStream << inStream.rdbuf();
std::cout<< outStringStream.str();
I get this exception "SSL Connection Unexpectedly Closed" on this line:
outStringStream << inStream.rdbuf();
Also if i instead try to read the response as:
Poco::StreamCopier::copyStream( inStream, outStringStream );
std::cout<< outStringStream.str();
I get empty response (No exception in this case).
The server returns a plain text in response. And i am getting it as response if using qt, but not through POCO. Please help me to read the response body. What could be the reason of this exception??
Also, one more thing if I read the response status as res.getStatus() and res.getReason() it returns 200Ok. I dont understand what is the issue with response body.
This code is working for me you can try.
std::istream& rs = _httpClientSession.receiveResponse(response);
memset(_response, 0, RESPONSE_BUFF_SIZE);
rs.read(_response, RESPONSE_BUFF_SIZE-1);
//below code is just to clear the istream
std::streamsize nRead = rs.gcount();
while( !rs.eof() || nRead != 0)
{
rs.read(_response, RESPONSE_BUFF_SIZE);
nRead = rs.gcount();
}
One more thing, in case of any exception you have to reset http session by invoking _httpClientSession.reset();