8 #ifndef _UWSGI_THRIFT_ASYNC_PROCESSOR_H_
9 #define _UWSGI_THRIFT_ASYNC_PROCESSOR_H_
11 #include <arpa/inet.h>
12 #include <boost/shared_ptr.hpp>
13 #include <thrift/Thrift.h>
14 #include <thrift/protocol/TBinaryProtocol.h>
15 #include <thrift/TApplicationException.h>
16 #include <unordered_set>
24 using namespace apache::thrift;
25 using namespace apache::thrift::protocol;
26 using namespace apache::thrift::transport;
31 template <
class handler_type>
43 std::ostringstream os;
44 os <<
"uwsgi_thrift_async_processor(" <<
this <<
")";
50 boost::shared_ptr<in_transport_type> in_transport(
new in_transport_type(request_p()));
51 boost::shared_ptr<out_transport_type> out_transport(
new out_transport_type(response_p()));
52 boost::shared_ptr<protocol_type> in_protocol(
new protocol_type(in_transport));
53 boost::shared_ptr<protocol_type> out_protocol(
new protocol_type(out_transport));
57 m_handler.reset(
new handler_type());
58 tdbg(get_string() <<
": created handler " << m_handler.get() << std::endl);
59 m_handler->set_uwsgi_task(
this);
60 m_handler->on_finish([
this, worker, out_protocol] {
61 if (m_handler->error()) {
62 tdbg(get_string() <<
": handler " << m_handler.get() <<
" finished with error(" << m_handler->error()
63 <<
"): " << m_handler->error_message() << std::endl);
64 write_thrift_error(std::string(
"Handler Error: ") + m_handler->error_message(),
65 m_handler->service_name(), out_protocol);
67 tdbg(get_string() <<
": handler " << m_handler.get() <<
" finished with no error" << std::endl);
69 out_protocol->writeMessageBegin(m_handler->service_name(), T_REPLY, m_seqid);
70 m_handler->result_base().__isset.success =
true;
71 m_handler->result_base().write(out_protocol.get());
72 out_protocol->writeMessageEnd();
73 out_protocol->getTransport()->writeEnd();
74 out_protocol->getTransport()->flush();
75 response().set_status(
"200 OK");
77 response().set_header(
"Content-Type",
"application/x-thrift");
79 if (error_code() == tasks_error::UNSET) {
89 in_protocol->readMessageBegin(fname, mtype, m_seqid);
90 if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) {
91 write_thrift_error(
"invalid message type", m_handler->service_name(), out_protocol);
92 send_thrift_response();
93 }
else if (fname != m_handler->service_name()) {
94 write_thrift_error(
"invalid method name", m_handler->service_name(), out_protocol);
95 send_thrift_response();
98 auto args = std::make_shared<typename handler_type::args_t>();
99 args->read(in_protocol.get());
100 in_protocol->readMessageEnd();
101 in_protocol->getTransport()->readEnd();
105 tdbg(get_string() <<
": calling service on handler " << m_handler.get() << std::endl);
106 m_handler->service(args);
108 }
catch (TException& e) {
109 write_thrift_error(std::string(
"TException: ") + e.what(), m_handler->service_name(), out_protocol);
110 send_thrift_response();
118 response().set_header(
"Content-Type",
"application/x-thrift");
128 boost::shared_ptr<protocol_type> out_protocol) {
129 response().set_header(
"X-UWSGI_THRIFT_ASYNC_PROCESSOR_ERROR", msg);
130 response().set_status(
"400 Bad Request");
131 TApplicationException ae(msg);
132 out_protocol->writeMessageBegin(service_name, T_EXCEPTION, m_seqid);
133 ae.write(out_protocol.get());
134 out_protocol->writeMessageEnd();
135 out_protocol->getTransport()->writeEnd();
136 out_protocol->getTransport()->flush();
147 #endif // _UWSGI_THRIFT_ASYNC_PROCESSOR_H_
std::unique_ptr< handler_type > m_handler
virtual ~uwsgi_thrift_async_processor()
void write_thrift_error(std::string msg, std::string service_name, boost::shared_ptr< protocol_type > out_protocol)
uwsgi_thrift_async_processor(net::socket &s)
The base class for the uwsgi protocol implementation.
bool exec_in_worker_ctx(task_func_t f)
std::string get_string() const
virtual bool handle_request()
void send_thrift_response()
Send the thrift response back to the caller.
TBinaryProtocol protocol_type