mirror of
https://github.com/valitydev/thrift.git
synced 2024-11-07 02:45:22 +00:00
THRIFT-1222 Unhandled exception for TEvhttpServer request
Patch: Alexandre Parenteau git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1147542 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a35944bfe2
commit
7e056e7572
14
compiler/cpp/src/generate/t_cpp_generator.cc
Normal file → Executable file
14
compiler/cpp/src/generate/t_cpp_generator.cc
Normal file → Executable file
@ -231,28 +231,28 @@ class t_cpp_generator : public t_oop_generator {
|
||||
std::string get_include_prefix(const t_program& program) const;
|
||||
|
||||
/**
|
||||
* True iff we should generate pure enums for Thrift enums, instead of wrapper classes.
|
||||
* True if we should generate pure enums for Thrift enums, instead of wrapper classes.
|
||||
*/
|
||||
bool gen_pure_enums_;
|
||||
|
||||
/**
|
||||
* True iff we should generate local reflection metadata for TDenseProtocol.
|
||||
* True if we should generate local reflection metadata for TDenseProtocol.
|
||||
*/
|
||||
bool gen_dense_;
|
||||
|
||||
/**
|
||||
* True iff we should generate templatized reader/writer methods.
|
||||
* True if we should generate templatized reader/writer methods.
|
||||
*/
|
||||
bool gen_templates_;
|
||||
|
||||
/**
|
||||
* True iff we should use a path prefix in our #include statements for other
|
||||
* True if we should use a path prefix in our #include statements for other
|
||||
* thrift-generated header files.
|
||||
*/
|
||||
bool use_include_prefix_;
|
||||
|
||||
/**
|
||||
* True iff we should generate "Continuation OBject"-style classes as well.
|
||||
* True if we should generate "Continuation OBject"-style classes as well.
|
||||
*/
|
||||
bool gen_cob_style_;
|
||||
|
||||
@ -4142,6 +4142,10 @@ string t_cpp_generator::get_include_prefix(const t_program& program) const {
|
||||
|
||||
|
||||
THRIFT_REGISTER_GENERATOR(cpp, "C++",
|
||||
" cob_style: Generate \"Continuation OBject\"-style classes.\n"
|
||||
" no_client_completion:\n"
|
||||
" Omit calls to completion__() in CobClient class.\n"
|
||||
" templates: Generate templatized reader/writer methods.\n"
|
||||
" pure_enums: Generate pure enums instead of wrapper classes.\n"
|
||||
" dense: Generate type specifications for the dense protocol.\n"
|
||||
" include_prefix: Use full include paths in generated files.\n"
|
||||
|
@ -70,11 +70,13 @@ libthrift_la_SOURCES = src/Thrift.cpp \
|
||||
src/server/TSimpleServer.cpp \
|
||||
src/server/TThreadPoolServer.cpp \
|
||||
src/server/TThreadedServer.cpp \
|
||||
src/async/TAsyncChannel.cpp \
|
||||
src/async/TAsyncChannel.cpp \
|
||||
src/processor/PeekProcessor.cpp
|
||||
|
||||
libthriftnb_la_SOURCES = src/server/TNonblockingServer.cpp \
|
||||
src/async/TAsyncProtocolProcessor.cpp
|
||||
src/async/TAsyncProtocolProcessor.cpp \
|
||||
src/async/TEvhttpServer.cpp \
|
||||
src/async/TEvhttpClientChannel.cpp
|
||||
|
||||
libthriftz_la_SOURCES = src/transport/TZlibTransport.cpp
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "TEvhttpClientChannel.h"
|
||||
#include <evhttp.h>
|
||||
#include "transport/TBufferTransports.h"
|
||||
|
||||
namespace apache { namespace thrift { namespace async {
|
||||
|
||||
|
@ -22,6 +22,10 @@
|
||||
#include "transport/TBufferTransports.h"
|
||||
#include <evhttp.h>
|
||||
|
||||
#ifndef HTTP_INTERNAL // libevent < 2
|
||||
#define HTTP_INTERNAL 500
|
||||
#endif
|
||||
|
||||
using apache::thrift::transport::TMemoryBuffer;
|
||||
|
||||
namespace apache { namespace thrift { namespace async {
|
||||
@ -98,7 +102,11 @@ TEvhttpServer::RequestContext::RequestContext(struct evhttp_request* req) : req(
|
||||
|
||||
|
||||
void TEvhttpServer::request(struct evhttp_request* req, void* self) {
|
||||
static_cast<TEvhttpServer*>(self)->process(req);
|
||||
try {
|
||||
static_cast<TEvhttpServer*>(self)->process(req);
|
||||
} catch(std::exception& e) {
|
||||
evhttp_send_reply(req, HTTP_INTERNAL, e.what(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,7 +87,7 @@ StressTestNonBlocking_LDADD = \
|
||||
THRIFT = $(top_builddir)/compiler/cpp/thrift
|
||||
|
||||
gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp: $(top_srcdir)/test/ThriftTest.thrift
|
||||
$(THRIFT) --gen cpp:templates $<
|
||||
$(THRIFT) --gen cpp:templates,cob_style -r $<
|
||||
|
||||
gen-cpp/ThriftTest.cpp gen-cpp/StressTest_types.cpp gen-cpp/StressTest_constants.cpp: $(top_srcdir)/test/StressTest.thrift
|
||||
$(THRIFT) --gen cpp $<
|
||||
@ -97,6 +97,7 @@ INCLUDES = \
|
||||
|
||||
AM_CPPFLAGS = $(BOOST_CPPFLAGS)
|
||||
AM_CXXFLAGS = -Wall
|
||||
AM_LDFLAGS = $(BOOST_LDFLAGS)
|
||||
|
||||
clean-local:
|
||||
$(RM) -r gen-cpp
|
||||
|
@ -29,9 +29,12 @@
|
||||
#include <transport/TTransportUtils.h>
|
||||
#include <transport/TSocket.h>
|
||||
#include <transport/TSSLSocket.h>
|
||||
#include <async/TEvhttpClientChannel.h>
|
||||
#include <server/TNonblockingServer.h> // <event.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <tr1/functional>
|
||||
|
||||
#include "ThriftTest.h"
|
||||
|
||||
@ -41,6 +44,9 @@ using namespace apache::thrift;
|
||||
using namespace apache::thrift::protocol;
|
||||
using namespace apache::thrift::transport;
|
||||
using namespace thrift::test;
|
||||
using namespace apache::thrift::async;
|
||||
|
||||
using std::tr1::placeholders::_1;
|
||||
|
||||
//extern uint32_t g_socket_syscalls;
|
||||
|
||||
@ -56,6 +62,33 @@ uint64_t now()
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void testString_clientReturn(const char* host, int port, event_base *base, TProtocolFactory* protocolFactory, ThriftTestCobClient* client) {
|
||||
try {
|
||||
string s;
|
||||
client->recv_testString(s);
|
||||
cout << "testString: " << s << endl;
|
||||
} catch (TException& exn) {
|
||||
cout << "Error: " << exn.what() << endl;
|
||||
}
|
||||
|
||||
event_base_loopbreak(base); // end test
|
||||
}
|
||||
|
||||
static void testVoid_clientReturn(const char* host, int port, event_base *base, TProtocolFactory* protocolFactory, ThriftTestCobClient* client) {
|
||||
try {
|
||||
client->recv_testVoid();
|
||||
cout << "testVoid" << endl;
|
||||
|
||||
// next test
|
||||
delete client;
|
||||
shared_ptr<TAsyncChannel> channel(new TEvhttpClientChannel(host, "/", host, port, base));
|
||||
client = new ThriftTestCobClient(channel, protocolFactory);
|
||||
client->testString(tr1::bind(testString_clientReturn, host, port, base, protocolFactory, _1), "Test");
|
||||
} catch (TException& exn) {
|
||||
cout << "Error: " << exn.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
string host = "localhost";
|
||||
int port = 9090;
|
||||
@ -71,7 +104,7 @@ int main(int argc, char** argv) {
|
||||
("host", program_options::value<string>(&host)->default_value(host), "Host to connect")
|
||||
("port", program_options::value<int>(&port)->default_value(port), "Port number to connect")
|
||||
("domain-socket", program_options::value<string>(&domain_socket)->default_value(domain_socket), "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port")
|
||||
("transport", program_options::value<string>(&transport_type)->default_value(transport_type), "Transport: buffered, framed, http")
|
||||
("transport", program_options::value<string>(&transport_type)->default_value(transport_type), "Transport: buffered, framed, http, evhttp")
|
||||
("protocol", program_options::value<string>(&protocol_type)->default_value(protocol_type), "Protocol: binary, json")
|
||||
("ssl", "Encrypted Transport using SSL")
|
||||
("testloops,n", program_options::value<int>(&numTests)->default_value(numTests), "Number of Tests")
|
||||
@ -99,6 +132,7 @@ int main(int argc, char** argv) {
|
||||
if (transport_type == "buffered") {
|
||||
} else if (transport_type == "framed") {
|
||||
} else if (transport_type == "http") {
|
||||
} else if (transport_type == "evhttp") {
|
||||
} else {
|
||||
throw invalid_argument("Unknown transport type "+transport_type);
|
||||
}
|
||||
@ -162,6 +196,25 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
if (transport_type.compare("evhttp") == 0) {
|
||||
event_base *base = event_base_new();
|
||||
cout << "Libevent Version: " << event_get_version() << endl;
|
||||
cout << "Libevent Method: " << event_base_get_method(base) << endl;
|
||||
#if LIBEVENT_VERSION_NUMBER >= 0x02000000
|
||||
cout << "Libevent Features: 0x" << hex << event_base_get_features(base) << endl;
|
||||
#endif
|
||||
|
||||
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
|
||||
|
||||
shared_ptr<TAsyncChannel> channel(new TEvhttpClientChannel(host.c_str(), "/", host.c_str(), port, base));
|
||||
ThriftTestCobClient* client = new ThriftTestCobClient(channel, protocolFactory.get());
|
||||
client->testVoid(tr1::bind(testVoid_clientReturn, host.c_str(), port, base, protocolFactory.get(), _1));
|
||||
|
||||
event_base_loop(base, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ThriftTestClient testClient(protocol);
|
||||
|
||||
uint64_t time_min = 0;
|
||||
|
150
test/cpp/src/TestServer.cpp
Normal file → Executable file
150
test/cpp/src/TestServer.cpp
Normal file → Executable file
@ -27,6 +27,9 @@
|
||||
#include <server/TSimpleServer.h>
|
||||
#include <server/TThreadedServer.h>
|
||||
#include <server/TThreadPoolServer.h>
|
||||
#include <async/TEvhttpServer.h>
|
||||
#include <async/TAsyncBufferProcessor.h>
|
||||
#include <async/TAsyncProtocolProcessor.h>
|
||||
#include <server/TNonblockingServer.h>
|
||||
#include <transport/TServerSocket.h>
|
||||
#include <transport/TSSLServerSocket.h>
|
||||
@ -52,6 +55,7 @@ using namespace apache::thrift::concurrency;
|
||||
using namespace apache::thrift::protocol;
|
||||
using namespace apache::thrift::transport;
|
||||
using namespace apache::thrift::server;
|
||||
using namespace apache::thrift::async;
|
||||
|
||||
using namespace thrift::test;
|
||||
|
||||
@ -345,6 +349,137 @@ class TestProcessorEventHandler : public TProcessorEventHandler {
|
||||
};
|
||||
|
||||
|
||||
class TestHandlerAsync : public ThriftTestCobSvIf {
|
||||
public:
|
||||
TestHandlerAsync(shared_ptr<TestHandler>& handler) : _delegate(handler) {}
|
||||
virtual ~TestHandlerAsync() {}
|
||||
|
||||
virtual void testVoid(std::tr1::function<void()> cob) {
|
||||
_delegate->testVoid();
|
||||
cob();
|
||||
}
|
||||
|
||||
virtual void testString(std::tr1::function<void(std::string const& _return)> cob, const std::string& thing) {
|
||||
std::string res;
|
||||
_delegate->testString(res, thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testByte(std::tr1::function<void(int8_t const& _return)> cob, const int8_t thing) {
|
||||
int8_t res = _delegate->testByte(thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testI32(std::tr1::function<void(int32_t const& _return)> cob, const int32_t thing) {
|
||||
int32_t res = _delegate->testI32(thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testI64(std::tr1::function<void(int64_t const& _return)> cob, const int64_t thing) {
|
||||
int64_t res = _delegate->testI64(thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testDouble(std::tr1::function<void(double const& _return)> cob, const double thing) {
|
||||
double res = _delegate->testDouble(thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testStruct(std::tr1::function<void(Xtruct const& _return)> cob, const Xtruct& thing) {
|
||||
Xtruct res;
|
||||
_delegate->testStruct(res, thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testNest(std::tr1::function<void(Xtruct2 const& _return)> cob, const Xtruct2& thing) {
|
||||
Xtruct2 res;
|
||||
_delegate->testNest(res, thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testMap(std::tr1::function<void(std::map<int32_t, int32_t> const& _return)> cob, const std::map<int32_t, int32_t> & thing) {
|
||||
std::map<int32_t, int32_t> res;
|
||||
_delegate->testMap(res, thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testStringMap(std::tr1::function<void(std::map<std::string, std::string> const& _return)> cob, const std::map<std::string, std::string> & thing) {
|
||||
std::map<std::string, std::string> res;
|
||||
_delegate->testStringMap(res, thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testSet(std::tr1::function<void(std::set<int32_t> const& _return)> cob, const std::set<int32_t> & thing) {
|
||||
std::set<int32_t> res;
|
||||
_delegate->testSet(res, thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testList(std::tr1::function<void(std::vector<int32_t> const& _return)> cob, const std::vector<int32_t> & thing) {
|
||||
std::vector<int32_t> res;
|
||||
_delegate->testList(res, thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testEnum(std::tr1::function<void(Numberz::type const& _return)> cob, const Numberz::type thing) {
|
||||
Numberz::type res = _delegate->testEnum(thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testTypedef(std::tr1::function<void(UserId const& _return)> cob, const UserId thing) {
|
||||
UserId res = _delegate->testTypedef(thing);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testMapMap(std::tr1::function<void(std::map<int32_t, std::map<int32_t, int32_t> > const& _return)> cob, const int32_t hello) {
|
||||
std::map<int32_t, std::map<int32_t, int32_t> > res;
|
||||
_delegate->testMapMap(res, hello);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testInsanity(std::tr1::function<void(std::map<UserId, std::map<Numberz::type, Insanity> > const& _return)> cob, const Insanity& argument) {
|
||||
std::map<UserId, std::map<Numberz::type, Insanity> > res;
|
||||
_delegate->testInsanity(res, argument);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testMulti(std::tr1::function<void(Xtruct const& _return)> cob, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map<int16_t, std::string> & arg3, const Numberz::type arg4, const UserId arg5) {
|
||||
Xtruct res;
|
||||
_delegate->testMulti(res, arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testException(std::tr1::function<void()> cob, std::tr1::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob, const std::string& arg) {
|
||||
try {
|
||||
_delegate->testException(arg);
|
||||
} catch(const apache::thrift::TException& e) {
|
||||
exn_cob(apache::thrift::TDelayedException::delayException(e));
|
||||
return;
|
||||
}
|
||||
cob();
|
||||
}
|
||||
|
||||
virtual void testMultiException(std::tr1::function<void(Xtruct const& _return)> cob, std::tr1::function<void(::apache::thrift::TDelayedException* _throw)> exn_cob, const std::string& arg0, const std::string& arg1) {
|
||||
Xtruct res;
|
||||
try {
|
||||
_delegate->testMultiException(res, arg0, arg1);
|
||||
} catch(const apache::thrift::TException& e) {
|
||||
exn_cob(apache::thrift::TDelayedException::delayException(e));
|
||||
return;
|
||||
}
|
||||
cob(res);
|
||||
}
|
||||
|
||||
virtual void testOneway(std::tr1::function<void()> cob, const int32_t secondsToSleep) {
|
||||
_delegate->testOneway(secondsToSleep);
|
||||
cob();
|
||||
}
|
||||
|
||||
protected:
|
||||
shared_ptr<TestHandler> _delegate;
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int port = 9090;
|
||||
bool ssl = false;
|
||||
@ -464,7 +599,7 @@ int main(int argc, char **argv) {
|
||||
// Factory
|
||||
shared_ptr<TTransportFactory> transportFactory;
|
||||
|
||||
if (transport_type == "http") {
|
||||
if (transport_type == "http" && server_type != "nonblocking") {
|
||||
shared_ptr<TTransportFactory> httpTransportFactory(new THttpServerTransportFactory());
|
||||
transportFactory = httpTransportFactory;
|
||||
} else if (transport_type == "framed") {
|
||||
@ -522,8 +657,17 @@ int main(int argc, char **argv) {
|
||||
threadedServer.serve();
|
||||
|
||||
} else if (server_type == "nonblocking") {
|
||||
TNonblockingServer nonblockingServer(testProcessor, port);
|
||||
nonblockingServer.serve();
|
||||
if(transport_type == "http") {
|
||||
shared_ptr<TestHandlerAsync> testHandlerAsync(new TestHandlerAsync(testHandler));
|
||||
shared_ptr<TAsyncProcessor> testProcessorAsync(new ThriftTestAsyncProcessor(testHandlerAsync));
|
||||
shared_ptr<TAsyncBufferProcessor> testBufferProcessor(new TAsyncProtocolProcessor(testProcessorAsync, protocolFactory));
|
||||
|
||||
TEvhttpServer nonblockingServer(testBufferProcessor, port);
|
||||
nonblockingServer.serve();
|
||||
} else {
|
||||
TNonblockingServer nonblockingServer(testProcessor, port);
|
||||
nonblockingServer.serve();
|
||||
}
|
||||
}
|
||||
|
||||
cout << "done." << endl;
|
||||
|
Loading…
Reference in New Issue
Block a user