Open RVelichko opened 3 years ago
What is the verbose output of the client?
Is the fetch callback invoked?
What is the verbose output of the client?
Instead of the client, I checked with standard curl curl -X POST http://127.0.0.1:8881/api/save_projects -d'[["1","Docs",""]]'
Is the fetch callback invoked?
*. hpp
#pragma once
namespace rest_srv {
struct IncapsulateData {};
using DataBuffer = std::vector
class RestSessionData { public: virtual void status(int status) = 0; virtual void send(const DataBuffer &data) = 0; virtual void read(const ReadDataFn &rd_data_fn) = 0; virtual std::multimap<std::string, std::string> parameters() = 0; };
using PRestSessionData = std::shared_ptr
class RestServer {
using PIncapsulateData = std::unique_ptr
int _port;
std::string _crt_path;
std::string _key_path;
PIncapsulateData _in_data;
public: RestServer(int port, const std::string &crt, const std::string &key, const ServiceReadyHndlFn &ready_fn);
void initHanler(const std::string &path, const std::string &method,
const RestSessionDataFn &handler_fn);
void start();
void stop();
}; } // namespace rest_srv
> *.cpp
namespace ph = std::placeholders; using namespace rest_srv;
using RestSession = restbed::Session;
using RestResource = restbed::Resource;
using RestSettings = restbed::Settings;
using RestService = restbed::Service;
using PRestSession = std::shared_ptr
class SessionData : public RestSessionData { RestSessionDataFn _callback_fn; RestSession *_session;
public: SessionData(const RestSessionDataFn &callback_fn) : _callback_fn(callback_fn) {}
void call(const PRestSession &session) {
if (_callback_fn) {
_session = session.get();
_callback_fn(this);
}
}
virtual void status(int status) { _session->close(status); }
virtual void send(const DataBuffer &data) {
const auto request = _session->get_request();
int content_length = 0;
request->get_header("Content-Length", content_length);
_session->fetch(
content_length, [data](const PRestSession session, const restbed::Bytes &body) {
std::string content_length = std::to_string(data.size());
session->set_header("Access-Control-Allow-Origin", "*");
session->set_header("Content-type", "application/json; charset=utf-8");
session->set_header("Access-Control-Allow-Methods",
"GET,PUT,POST,DELETE,PATCH,OPTIONS");
session->close(restbed::OK, data, {{"Content-Length", content_length.c_str()}});
});
}
virtual void read(const ReadDataFn &rd_data_fn) {
auto request = _session->get_request();
size_t length = 0;
request->get_header("Content-Length", length);
_session->fetch(length, [](const PRestSession session, const restbed::Bytes &body) {
std::cout << "### BODY " << std::string(body.begin(), body.end()) << "\n" << std::flush;
session->close(200, "", {{"Content-Length", "0"}});
//[rd_data_fn](const PRestSession session, const restbed::Bytes &body) {
// if (rd_data_fn(body)) {
// session->close(200, "",
// {{"Content-Length", "0"}});
// } else {
// session->close(500, "ERROR",
// {{"Content-Length", "5"}});
// }
});
}
virtual std::multimap<std::string, std::string> parameters() {
const auto request = _session->get_request();
return request->get_query_parameters();
}
};
void SessionHandler(const PRestSession &session, const PRestSessionData &sdata) { static_cast<SessionData *>(sdata.get())->call(session); }
void ReadyHandler(RestService &srv, const ServiceReadyHndlFn &ready_fn) { if (ready_fn) { ready_fn(); } }
struct IncapsulateService : IncapsulateData { RestService srv; }; ////////////////////////////////////////////////////////////////////////////////////////////////////
void RestServer::initHanler(const std::string &path, const std::string &method,
const RestSessionDataFn &handler_fn) {
PRestSessionData sdata = std::make_shared
RestServer::RestServer(int port, const std::string &crt, const std::string &key,
const ServiceReadyHndlFn &ready_fn)
: _port(port),
_crt_path(crt),
_key_path(key),
_in_data(std::make_unique
void RestServer::start() {
auto settings = std::make_shared
void RestServer::stop() { static_cast<IncapsulateService *>(_in_data.get())->srv.stop(); }
Please read one of the supplied examples to validate your implementation.
Your examples don't compile at all.
int content_length = request-> get_header ("Content-Length", 0); no such function!
Code I It works for you on Ubuntu 20.02, but does not work on Centos 7.
That issue is related to
template <typename Type, std::enable_if_t< std::is_arithmetic< std::remove_reference_t< Type > >::value > * = nullptr> inline
Type get_header( const std::string& name, const Type default_value ) const
{
return Common::parse_parameter( get_header( name ), default_value );
}
I tried this: int content_length = 10000; request-> get_header ("Content-Length", content_length);
nothing has changed. On Centos7 - the body is always empty.
Speaking of examples: https://stackoverflow.com/questions/39275257/restbed-http-client-empty-body
I suspect your content_length is empty.
void post_method_handler( const shared_ptr< Session > session )
{
const auto request = session->get_request( );
size_t content_length = request->get_header( "Content-Length", 1024 );
session->fetch( content_length, [ request ]( const shared_ptr< Session > session, const Bytes & body )
{
fprintf( stdout, "%.*s\n", ( int ) body.size( ), body.data( ) );
session->close( OK, "Hello, World!", { { "Content-Length", "13" }, { "Connection", "close" } } );
} );
}
Speaking of examples: https://stackoverflow.com/questions/39275257/restbed-http-client-empty-body
This was caused by user error as can be seen in the top answer.
This link is in support of the fact that the example on the github is not correct.
OK, so you have no direct issue with restbed you just require the documentation updated?
If this is the case we have an outstanding ticket for this and it will be done in the 4.8 release cycle.
Please also note the issue is one of compiler implementation.
I answered your recommendation to see examples. I looked at them - they don't compile. And the error has not been fixed. I am the second in whom it manifested itself. But the repost bug was simply closed. Once again, it works on Ubuntu, but not on Centos7.
So if you hardcode the content_length to a known value you are still receiving no body?
auto request = _session->get_request();
size_t length = 5
_session->fetch(length, [](const PRestSession session, const restbed::Bytes &body) {
fprintf( stderr, "%*s\n", 5, body.data( ));
session->close(200, "", {{"Content-Length", "0"}});
});
That's the strangeness - under Centos 7 - the body is always empty.
I can roll back the version of my server a little later and try it more carefully, look for this problem with you. So far I rewrote everything on POCO.
That's the strangeness - under Centos 7 - the body is always empty.
What version of the compiler are you using? We don't see this on PopOS, FreeBSD, Ubuntu, MacOSX, Windows with GCC, Clang and MSVC.
On Centos 7 /opt/rh/devtoolset-9/root/usr/bin/g++ --version g++ (GCC) 9.3.1 20200408 (Red Hat 9.3.1-2) Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
On Ubuntu g++ --version g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Code example in project:
Testing: curl -X POST http://127.0.0.1:8881/api/save_projects -d'[["1","Docs",""]]'
Result in server: Body is empty, but pcapdum contains a line "[["1","Docs",""]]" in the post request.