Ruby bindings for the Apache Thrift RPC system. The gem contains the runtime types, transports, protocols, and servers used by generated Ruby code for both clients and services.
gem install thriftbundle install, gem build thrift.gemspec, then install the
resulting thrift-*.gem. The native accelerator is built when the gem is
installed on supported runtimes.The Ruby library does not include the Thrift compiler. Use a compiler built from the root of this repository to generate Ruby bindings:
thrift --gen rb path/to/service.thrift
# with namespaced modules
thrift --gen rb:namespaced --recurse path/to/service.thrift
Generated files are typically written to gen-rb/ and can be required
directly from your application.
$:.push File.expand_path('gen-rb', __dir__)
require 'thrift'
require 'calculator'
socket = Thrift::Socket.new('localhost', 9090)
transport = Thrift::BufferedTransport.new(socket)
protocol = Thrift::BinaryProtocol.new(transport)
client = Calculator::Client.new(protocol)
transport.open
puts client.add(1, 1)
transport.close
$:.push File.expand_path('gen-rb', __dir__)
require 'thrift'
require 'calculator'
class CalculatorHandler
def add(a, b)
a + b
end
end
handler = CalculatorHandler.new
processor = Calculator::Processor.new(handler)
server_transport = Thrift::ServerSocket.new(9090)
transport_factory = Thrift::BufferedTransportFactory.new
protocol_factory = Thrift::BinaryProtocolFactory.new
server = Thrift::ThreadedServer.new(processor, server_transport,
transport_factory, protocol_factory)
server.serve
Ruby HTTP transport can be mounted as a Rack application, so applications can
run Thrift on an existing Rack server such as Puma or Falcon.
The examples below use the generated Calculator::Processor and the
CalculatorHandler from Basic Server Usage.
# config.ru
require 'thrift'
require 'thrift/server/rack_application'
processor = Calculator::Processor.new(CalculatorHandler.new)
run Thrift::RackApplication.new(processor)
For Rails or another Rack router, mount the endpoint at the route that should receive Thrift HTTP requests:
# config/routes.rb
processor = Calculator::Processor.new(CalculatorHandler.new)
mount Thrift::RackApplication.new(processor) => "/thrift"
bundle exec rake spec runs the Ruby specs. It expects a built Thrift
compiler at ../../compiler/cpp/thrift.bundle exec rake test runs the cross-language test suite; it must be
executed from a full Thrift checkout.bundle exec rake build_ext (implicit in the tasks above) compiles the
optional native extension that accelerates protocols and buffers.tutorial/rb/RubyClient.rb and tutorial/rb/RubyServer.rblib/rb/benchmarktest/rb/benchmarks/protocol_benchmark.rblib/rb/speclib/rb/test/fuzztest/rbRuby HTTP servers now share one Rack endpoint. Run Thrift::RackApplication
as a Rack app, or mount it at one path in an app such as Rails. The
cross-language HTTP tests now cover Puma and Falcon.
Thrift::MongrelHTTPServer has been removed because Mongrel no longer works
with supported Ruby versions. To migrate, mount Thrift::RackApplication in
a supported Rack server. See Rack HTTP Endpoint.
Thrift::ThinHTTPServer is deprecated because Thin is no longer maintained.
Its EventMachine dependency also does not build on new Ruby development
versions. Creating a Thin server now prints a warning. Move to
Thrift::RackApplication with a supported Rack server such as Puma or Falcon.
Thrift::SSLSocket now verifies peers by default when no SSL context is
provided. It creates a context that uses the system certificate store. A
supplied SSL context is not reconfigured by Thrift, so the application is
responsible for its verification mode and trust sources. A newly constructed
OpenSSL::SSL::SSLContext defaults to OpenSSL::SSL::VERIFY_NONE; configuring
a trust source alone does not enable certificate chain verification. The server
certificate must still match the connection hostname.
Thrift::Socket#open now raises
Thrift::TransportException::ALREADY_OPEN when the TCP transport is already
open. Close the transport before opening it again.
Connect timeout handling changed for both Thrift::Socket and
Thrift::SSLSocket.
timeout == nil and timeout == 0 now use blocking connect/open semantics.
Older releases already treated nil that way, but treated 0 differently
across operations: read and write used the blocking path, plain TCP
open used a zero-length poll, and TLS open could spin in the handshake
retry loop.Thrift::TransportException::TIMED_OUT. Older releases could report the same
condition as NOT_OPEN, and Thrift::SSLSocket could keep retrying the
handshake after the wait timed out.If your application matched NOT_OPEN for connect timeout handling, update it
to handle TIMED_OUT. If you relied on timeout = 0 meaning immediate failure
or on repeated retries extending the effective timeout during TCP fallback or
TLS handshake, update those call paths before upgrading.
Ruby server socket transports now apply a 5-second timeout to accepted client
sockets by default. This prevents stalled clients from blocking server threads
indefinitely during response writes. Applications that intentionally require
blocking accepted sockets can pass client_timeout: nil or client_timeout: 0
when constructing Thrift::ServerSocket, Thrift::SSLServerSocket, or
Thrift::UNIXServerSocket.
Generated Ruby structs and unions now suffix field ID constants as
*_FIELD_ID instead of exposing bare uppercased field names. For example,
MyStruct::FOO becomes MyStruct::FOO_FIELD_ID. This avoids collisions with
the generated FIELDS metadata hash for field names such as fields, but it
is a source-compatible break if your application referenced the old constants
directly. Regenerate Ruby code and update those constant references atomically.
Ruby binary protocol writers now enforce signed Thrift integer ranges before
serializing values. byte, i16, i32, and i64 writes reject values outside
their declared signed ranges, and binary/string/container sizes must fit in a
non-negative signed i32 length. Older releases could silently wrap or clip
some out-of-range values, such as writing 255 as a byte that read back as
-1. This applies to both Thrift::BinaryProtocol and
Thrift::BinaryProtocolAccelerated.
The documented source-build flow now effectively requires Ruby 2.7+.
The committed development bundle no longer resolves on Ruby 2.6
(json-2.18.1 requires ruby version >= 2.7), so building and testing this
library from source should be treated as 2.7+.
Generated structs and unions now consistently raise
Thrift::ProtocolException::INVALID_DATA for invalid payloads such as unset
required fields, invalid enum values, or invalid union state. If your
application or tests matched older exception types or messages, update them.
Regenerated Ruby clients now validate replies more strictly. Mismatched reply
message types, method names, or sequence IDs raise
Thrift::ApplicationException::INVALID_MESSAGE_TYPE,
Thrift::ApplicationException::WRONG_METHOD_NAME, or
Thrift::ApplicationException::BAD_SEQUENCE_ID. If you relied on older,
looser reply handling in servers, proxies, or tests, regenerate and update
those call paths together.
Generated Ruby clients have never been safe to share across concurrent threads. A client tracks pending sequence IDs on a single reply stream, so use one client/transport pair per thread or serialize access yourself.
Treat Thrift::ApplicationException::BAD_SEQUENCE_ID as a correctness bug
that needs immediate attention. It means the client read a reply whose
sequence ID did not match the next pending request, so the connection may
already be out of sync and you may be reading a reply intended for a
different call. The most common cause is sharing one client across threads,
but a buggy proxy or server can also cause it.
Ruby development and CI moved to Ruby 2.4+, but the runtime still claimed
support for older interpreters. Treat Ruby < 2.4 on the 0.13.x line as
best-effort, not guaranteed.
T* constants or legacy require paths such as
TBinaryProtocol -> Thrift::BinaryProtocol.rb:namespaced changes the generated file layout. Flat output from
thrift --gen rb and namespaced output from thrift --gen rb:namespaced
use different require paths, so switch them atomically with regenerated code.
# --gen rb
require 'calculator'
# --gen rb:namespaced
require 'my_namespace/calculator'
0.25.0, note that Thrift::SSLSocket now verifies peers
by default when it creates the SSL context. Supplied contexts are used
unchanged and must configure their own verification mode and trust sources.
A blank supplied context defaults to OpenSSL::SSL::VERIFY_NONE. Hostname
checking is performed for both supplied and default contexts.0.25.0, close a Thrift::Socket before calling open
again. A duplicate open now raises
Thrift::TransportException::ALREADY_OPEN.0.24.0, treat timeout on Thrift::Socket and
Thrift::SSLSocket as one budget for the whole open path. For
Thrift::SSLSocket, that includes both the TCP connect and the TLS
handshake.0.24.0, handle connect/open timeout expiry as
Thrift::TransportException::TIMED_OUT instead of NOT_OPEN.Thrift::ApplicationException::BAD_SEQUENCE_ID, treat the
connection as out of sync. Close it, create a new client/transport pair, and
investigate the root cause before retrying.thrift --gen rb and thrift --gen rb:namespaced,
regenerate all Ruby output and update require paths in the same change.thrift_native extension changes which implementation you are
running. It replaces
Thrift::Struct, Thrift::Union, and Thrift::CompactProtocol methods
with C implementations in place. Thrift::BinaryProtocol remains available
in pure Ruby, and the C-backed binary protocol is opt-in through
Thrift::BinaryProtocolAcceleratedFactory or
Thrift::BinaryProtocolAccelerated when that class is available.Thrift::NonblockingServer expects framed input. Use
Thrift::FramedTransport with it on the wire.HTTPS client transport and Thrift::SSLSocket verify peers by default.
When no SSL context is provided, Thrift::SSLSocket creates one with peer
verification and the system certificate store. Thrift passes a supplied
context to OpenSSL without reconfiguring it. Thrift::SSLSocket always
checks the certificate against server_hostname (or the connection host by
default). OpenSSL::SSL::SSLContext.new defaults to
OpenSSL::SSL::VERIFY_NONE, and setting ca_file, ca_path, or cert_store
does not enable verification by itself. Set verify_mode explicitly when
supplying a context. For example, to disable certificate chain verification:
context = OpenSSL::SSL::SSLContext.new
context.verify_mode = OpenSSL::SSL::VERIFY_NONE
socket = Thrift::SSLSocket.new(host, port, nil, context)