thrift-mavericks 0.8.0 → 0.9.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/ext/binary_protocol_accelerated.c +21 -2
- data/ext/bytes.c +36 -0
- data/ext/bytes.h +31 -0
- data/ext/compact_protocol.c +24 -7
- data/ext/constants.h +5 -5
- data/ext/extconf.rb +3 -1
- data/ext/memory_buffer.c +11 -8
- data/ext/protocol.c +0 -185
- data/ext/protocol.h +0 -20
- data/ext/struct.c +0 -3
- data/ext/thrift_native.c +10 -11
- data/lib/thrift.rb +3 -0
- data/lib/thrift/bytes.rb +131 -0
- data/lib/thrift/exceptions.rb +3 -0
- data/lib/thrift/protocol/base_protocol.rb +96 -9
- data/lib/thrift/protocol/binary_protocol.rb +15 -7
- data/lib/thrift/protocol/compact_protocol.rb +14 -6
- data/lib/thrift/protocol/json_protocol.rb +766 -0
- data/lib/thrift/server/mongrel_http_server.rb +2 -0
- data/lib/thrift/server/thin_http_server.rb +91 -0
- data/lib/thrift/struct.rb +1 -1
- data/lib/thrift/struct_union.rb +2 -2
- data/lib/thrift/transport/base_transport.rb +22 -20
- data/lib/thrift/transport/buffered_transport.rb +16 -10
- data/lib/thrift/transport/framed_transport.rb +11 -10
- data/lib/thrift/transport/http_client_transport.rb +11 -6
- data/lib/thrift/transport/io_stream_transport.rb +1 -1
- data/lib/thrift/transport/memory_buffer_transport.rb +6 -6
- data/lib/thrift/transport/socket.rb +4 -2
- data/spec/ThriftSpec.thrift +52 -1
- data/spec/base_protocol_spec.rb +108 -51
- data/spec/base_transport_spec.rb +49 -50
- data/spec/binary_protocol_accelerated_spec.rb +9 -13
- data/spec/binary_protocol_spec.rb +15 -10
- data/spec/binary_protocol_spec_shared.rb +92 -12
- data/spec/bytes_spec.rb +160 -0
- data/spec/client_spec.rb +13 -14
- data/spec/compact_protocol_spec.rb +4 -5
- data/spec/exception_spec.rb +39 -40
- data/spec/gen-rb/thrift_spec_types.rb +192 -0
- data/spec/http_client_spec.rb +65 -9
- data/spec/json_protocol_spec.rb +513 -0
- data/spec/nonblocking_server_spec.rb +18 -20
- data/spec/processor_spec.rb +13 -16
- data/spec/serializer_spec.rb +17 -19
- data/spec/server_socket_spec.rb +6 -7
- data/spec/server_spec.rb +46 -58
- data/spec/socket_spec.rb +11 -11
- data/spec/socket_spec_shared.rb +1 -1
- data/spec/spec_helper.rb +13 -10
- data/spec/struct_nested_containers_spec.rb +191 -0
- data/spec/struct_spec.rb +84 -86
- data/spec/thin_http_server_spec.rb +140 -0
- data/spec/types_spec.rb +65 -66
- data/spec/union_spec.rb +57 -47
- data/spec/unix_socket_spec.rb +8 -9
- metadata +72 -14
- data/spec/mongrel_http_server_spec.rb +0 -117
@@ -20,6 +20,7 @@
|
|
20
20
|
require 'mongrel'
|
21
21
|
|
22
22
|
## Sticks a service on a URL, using mongrel to do the HTTP work
|
23
|
+
# <b>DEPRECATED:</b> Please use <tt>Thrift::ThinHTTPServer</tt> instead.
|
23
24
|
module Thrift
|
24
25
|
class MongrelHTTPServer < BaseServer
|
25
26
|
class Handler < Mongrel::HttpHandler
|
@@ -43,6 +44,7 @@ module Thrift
|
|
43
44
|
end
|
44
45
|
|
45
46
|
def initialize(processor, opts={})
|
47
|
+
Kernel.warn "[DEPRECATION WARNING] `Thrift::MongrelHTTPServer` is deprecated. Please use `Thrift::ThinHTTPServer` instead."
|
46
48
|
port = opts[:port] || 80
|
47
49
|
ip = opts[:ip] || "0.0.0.0"
|
48
50
|
path = opts[:path] || ""
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'rack'
|
21
|
+
require 'thin'
|
22
|
+
|
23
|
+
##
|
24
|
+
# Wraps the Thin web server to provide a Thrift server over HTTP.
|
25
|
+
module Thrift
|
26
|
+
class ThinHTTPServer < BaseServer
|
27
|
+
|
28
|
+
##
|
29
|
+
# Accepts a Thrift::Processor
|
30
|
+
# Options include:
|
31
|
+
# * :port
|
32
|
+
# * :ip
|
33
|
+
# * :path
|
34
|
+
# * :protocol_factory
|
35
|
+
def initialize(processor, options={})
|
36
|
+
port = options[:port] || 80
|
37
|
+
ip = options[:ip] || "0.0.0.0"
|
38
|
+
path = options[:path] || "/"
|
39
|
+
protocol_factory = options[:protocol_factory] || BinaryProtocolFactory.new
|
40
|
+
app = RackApplication.for(path, processor, protocol_factory)
|
41
|
+
@server = Thin::Server.new(ip, port, app)
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Starts the server
|
46
|
+
def serve
|
47
|
+
@server.start
|
48
|
+
end
|
49
|
+
|
50
|
+
class RackApplication
|
51
|
+
|
52
|
+
THRIFT_HEADER = "application/x-thrift"
|
53
|
+
|
54
|
+
def self.for(path, processor, protocol_factory)
|
55
|
+
Rack::Builder.new do
|
56
|
+
use Rack::CommonLogger
|
57
|
+
use Rack::ShowExceptions
|
58
|
+
use Rack::Lint
|
59
|
+
map path do
|
60
|
+
run lambda { |env|
|
61
|
+
request = Rack::Request.new(env)
|
62
|
+
if RackApplication.valid_thrift_request?(request)
|
63
|
+
RackApplication.successful_request(request, processor, protocol_factory)
|
64
|
+
else
|
65
|
+
RackApplication.failed_request
|
66
|
+
end
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.successful_request(rack_request, processor, protocol_factory)
|
73
|
+
response = Rack::Response.new([], 200, {'Content-Type' => THRIFT_HEADER})
|
74
|
+
transport = IOStreamTransport.new rack_request.body, response
|
75
|
+
protocol = protocol_factory.get_protocol transport
|
76
|
+
processor.process protocol, protocol
|
77
|
+
response
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.failed_request
|
81
|
+
Rack::Response.new(['Not Found'], 404, {'Content-Type' => THRIFT_HEADER})
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.valid_thrift_request?(rack_request)
|
85
|
+
rack_request.post? && rack_request.env["CONTENT_TYPE"] == THRIFT_HEADER
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
data/lib/thrift/struct.rb
CHANGED
data/lib/thrift/struct_union.rb
CHANGED
@@ -101,7 +101,7 @@ module Thrift
|
|
101
101
|
end
|
102
102
|
iprot.read_set_end
|
103
103
|
else
|
104
|
-
value = iprot.read_type(field
|
104
|
+
value = iprot.read_type(field)
|
105
105
|
end
|
106
106
|
value
|
107
107
|
end
|
@@ -110,7 +110,7 @@ module Thrift
|
|
110
110
|
if is_container? field[:type]
|
111
111
|
write_container(oprot, value, field)
|
112
112
|
else
|
113
|
-
oprot.write_type(field
|
113
|
+
oprot.write_type(field, value)
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
@@ -35,22 +35,14 @@ module Thrift
|
|
35
35
|
end
|
36
36
|
|
37
37
|
module TransportUtils
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def self.set_string_byte(string, index, byte)
|
44
|
-
string.setbyte(index, byte)
|
45
|
-
end
|
46
|
-
else
|
47
|
-
def self.get_string_byte(string, index)
|
48
|
-
string[index]
|
49
|
-
end
|
38
|
+
# Deprecated: Use Thrift::Bytes instead
|
39
|
+
def self.get_string_byte(string, index)
|
40
|
+
Bytes.get_string_byte(string, index)
|
41
|
+
end
|
50
42
|
|
51
|
-
|
52
|
-
|
53
|
-
|
43
|
+
# Deprecated: Use Thrift::Bytes instead
|
44
|
+
def self.set_string_byte(string, index, byte)
|
45
|
+
Bytes.set_string_byte(string, index, byte)
|
54
46
|
end
|
55
47
|
end
|
56
48
|
|
@@ -61,6 +53,11 @@ module Thrift
|
|
61
53
|
|
62
54
|
def close; end
|
63
55
|
|
56
|
+
# Reads a number of bytes from the transports. In Ruby 1.9+, the String returned will have a BINARY (aka ASCII8BIT) encoding.
|
57
|
+
#
|
58
|
+
# sz - The number of bytes to read from the transport.
|
59
|
+
#
|
60
|
+
# Returns a String acting as a byte buffer.
|
64
61
|
def read(sz)
|
65
62
|
raise NotImplementedError
|
66
63
|
end
|
@@ -68,7 +65,7 @@ module Thrift
|
|
68
65
|
# Returns an unsigned byte as a Fixnum in the range (0..255).
|
69
66
|
def read_byte
|
70
67
|
buf = read_all(1)
|
71
|
-
return
|
68
|
+
return Bytes.get_string_byte(buf, 0)
|
72
69
|
end
|
73
70
|
|
74
71
|
# Reads size bytes and copies them into buffer[0..size].
|
@@ -76,14 +73,14 @@ module Thrift
|
|
76
73
|
tmp = read_all(size)
|
77
74
|
i = 0
|
78
75
|
tmp.each_byte do |byte|
|
79
|
-
|
76
|
+
Bytes.set_string_byte(buffer, i, byte)
|
80
77
|
i += 1
|
81
78
|
end
|
82
79
|
i
|
83
80
|
end
|
84
81
|
|
85
82
|
def read_all(size)
|
86
|
-
return
|
83
|
+
return Bytes.empty_byte_buffer if size <= 0
|
87
84
|
buf = read(size)
|
88
85
|
while (buf.length < size)
|
89
86
|
chunk = read(size - buf.length)
|
@@ -92,7 +89,12 @@ module Thrift
|
|
92
89
|
|
93
90
|
buf
|
94
91
|
end
|
95
|
-
|
92
|
+
|
93
|
+
# Writes the byte buffer to the transport. In Ruby 1.9+, the buffer will be forced into BINARY encoding.
|
94
|
+
#
|
95
|
+
# buf - A String acting as a byte buffer.
|
96
|
+
#
|
97
|
+
# Returns nothing.
|
96
98
|
def write(buf); end
|
97
99
|
alias_method :<<, :write
|
98
100
|
|
@@ -104,4 +106,4 @@ module Thrift
|
|
104
106
|
return trans
|
105
107
|
end
|
106
108
|
end
|
107
|
-
end
|
109
|
+
end
|
@@ -24,8 +24,8 @@ module Thrift
|
|
24
24
|
|
25
25
|
def initialize(transport)
|
26
26
|
@transport = transport
|
27
|
-
@wbuf =
|
28
|
-
@rbuf =
|
27
|
+
@wbuf = Bytes.empty_byte_buffer
|
28
|
+
@rbuf = Bytes.empty_byte_buffer
|
29
29
|
@index = 0
|
30
30
|
end
|
31
31
|
|
@@ -44,12 +44,12 @@ module Thrift
|
|
44
44
|
|
45
45
|
def read(sz)
|
46
46
|
@index += sz
|
47
|
-
ret = @rbuf.slice(@index - sz, sz) ||
|
47
|
+
ret = @rbuf.slice(@index - sz, sz) || Bytes.empty_byte_buffer
|
48
48
|
|
49
49
|
if ret.length == 0
|
50
50
|
@rbuf = @transport.read([sz, DEFAULT_BUFFER].max)
|
51
51
|
@index = sz
|
52
|
-
ret = @rbuf.slice(0, sz) ||
|
52
|
+
ret = @rbuf.slice(0, sz) || Bytes.empty_byte_buffer
|
53
53
|
end
|
54
54
|
|
55
55
|
ret
|
@@ -65,9 +65,15 @@ module Thrift
|
|
65
65
|
# The read buffer has some data now, read a single byte. Using get_string_byte() avoids
|
66
66
|
# allocating a temp string of size 1 unnecessarily.
|
67
67
|
@index += 1
|
68
|
-
return
|
68
|
+
return Bytes.get_string_byte(@rbuf, @index - 1)
|
69
69
|
end
|
70
70
|
|
71
|
+
# Reads a number of bytes from the transport into the buffer passed.
|
72
|
+
#
|
73
|
+
# buffer - The String (byte buffer) to write data to; this is assumed to have a BINARY encoding.
|
74
|
+
# size - The number of bytes to read from the transport and write to the buffer.
|
75
|
+
#
|
76
|
+
# Returns the number of bytes read.
|
71
77
|
def read_into_buffer(buffer, size)
|
72
78
|
i = 0
|
73
79
|
while i < size
|
@@ -78,8 +84,8 @@ module Thrift
|
|
78
84
|
end
|
79
85
|
|
80
86
|
# The read buffer has some data now, so copy bytes over to the output buffer.
|
81
|
-
byte =
|
82
|
-
|
87
|
+
byte = Bytes.get_string_byte(@rbuf, @index)
|
88
|
+
Bytes.set_string_byte(buffer, i, byte)
|
83
89
|
@index += 1
|
84
90
|
i += 1
|
85
91
|
end
|
@@ -87,13 +93,13 @@ module Thrift
|
|
87
93
|
end
|
88
94
|
|
89
95
|
def write(buf)
|
90
|
-
@wbuf << buf
|
96
|
+
@wbuf << Bytes.force_binary_encoding(buf)
|
91
97
|
end
|
92
98
|
|
93
99
|
def flush
|
94
|
-
|
100
|
+
unless @wbuf.empty?
|
95
101
|
@transport.write(@wbuf)
|
96
|
-
@wbuf =
|
102
|
+
@wbuf = Bytes.empty_byte_buffer
|
97
103
|
end
|
98
104
|
|
99
105
|
@transport.flush
|
@@ -22,8 +22,8 @@ module Thrift
|
|
22
22
|
class FramedTransport < BaseTransport
|
23
23
|
def initialize(transport, read=true, write=true)
|
24
24
|
@transport = transport
|
25
|
-
@rbuf =
|
26
|
-
@wbuf =
|
25
|
+
@rbuf = Bytes.empty_byte_buffer
|
26
|
+
@wbuf = Bytes.empty_byte_buffer
|
27
27
|
@read = read
|
28
28
|
@write = write
|
29
29
|
@index = 0
|
@@ -44,12 +44,12 @@ module Thrift
|
|
44
44
|
def read(sz)
|
45
45
|
return @transport.read(sz) unless @read
|
46
46
|
|
47
|
-
return
|
47
|
+
return Bytes.empty_byte_buffer if sz <= 0
|
48
48
|
|
49
49
|
read_frame if @index >= @rbuf.length
|
50
50
|
|
51
51
|
@index += sz
|
52
|
-
@rbuf.slice(@index - sz, sz) ||
|
52
|
+
@rbuf.slice(@index - sz, sz) || Bytes.empty_byte_buffer
|
53
53
|
end
|
54
54
|
|
55
55
|
def read_byte
|
@@ -60,7 +60,7 @@ module Thrift
|
|
60
60
|
# The read buffer has some data now, read a single byte. Using get_string_byte() avoids
|
61
61
|
# allocating a temp string of size 1 unnecessarily.
|
62
62
|
@index += 1
|
63
|
-
return
|
63
|
+
return Bytes.get_string_byte(@rbuf, @index - 1)
|
64
64
|
end
|
65
65
|
|
66
66
|
def read_into_buffer(buffer, size)
|
@@ -69,18 +69,18 @@ module Thrift
|
|
69
69
|
read_frame if @index >= @rbuf.length
|
70
70
|
|
71
71
|
# The read buffer has some data now, so copy bytes over to the output buffer.
|
72
|
-
byte =
|
73
|
-
|
72
|
+
byte = Bytes.get_string_byte(@rbuf, @index)
|
73
|
+
Bytes.set_string_byte(buffer, i, byte)
|
74
74
|
@index += 1
|
75
75
|
i += 1
|
76
76
|
end
|
77
77
|
i
|
78
78
|
end
|
79
79
|
|
80
|
-
|
81
|
-
def write(buf,sz=nil)
|
80
|
+
def write(buf, sz=nil)
|
82
81
|
return @transport.write(buf) unless @write
|
83
82
|
|
83
|
+
buf = Bytes.force_binary_encoding(buf)
|
84
84
|
@wbuf << (sz ? buf[0...sz] : buf)
|
85
85
|
end
|
86
86
|
|
@@ -92,10 +92,11 @@ module Thrift
|
|
92
92
|
return @transport.flush unless @write
|
93
93
|
|
94
94
|
out = [@wbuf.length].pack('N')
|
95
|
+
# Array#pack should return a BINARY encoded String, so it shouldn't be necessary to force encoding
|
95
96
|
out << @wbuf
|
96
97
|
@transport.write(out)
|
97
98
|
@transport.flush
|
98
|
-
@wbuf =
|
99
|
+
@wbuf = Bytes.empty_byte_buffer
|
99
100
|
end
|
100
101
|
|
101
102
|
private
|
@@ -20,21 +20,23 @@
|
|
20
20
|
|
21
21
|
require 'net/http'
|
22
22
|
require 'net/https'
|
23
|
+
require 'openssl'
|
23
24
|
require 'uri'
|
24
25
|
require 'stringio'
|
25
26
|
|
26
27
|
module Thrift
|
27
28
|
class HTTPClientTransport < BaseTransport
|
28
29
|
|
29
|
-
def initialize(url)
|
30
|
+
def initialize(url, opts = {})
|
30
31
|
@url = URI url
|
31
32
|
@headers = {'Content-Type' => 'application/x-thrift'}
|
32
|
-
@outbuf =
|
33
|
+
@outbuf = Bytes.empty_byte_buffer
|
34
|
+
@ssl_verify_mode = opts.fetch(:ssl_verify_mode, OpenSSL::SSL::VERIFY_PEER)
|
33
35
|
end
|
34
36
|
|
35
37
|
def open?; true end
|
36
38
|
def read(sz); @inbuf.read sz end
|
37
|
-
def write(buf); @outbuf << buf end
|
39
|
+
def write(buf); @outbuf << Bytes.force_binary_encoding(buf) end
|
38
40
|
|
39
41
|
def add_headers(headers)
|
40
42
|
@headers = @headers.merge(headers)
|
@@ -42,10 +44,13 @@ module Thrift
|
|
42
44
|
|
43
45
|
def flush
|
44
46
|
http = Net::HTTP.new @url.host, @url.port
|
45
|
-
http.use_ssl = @url.scheme ==
|
46
|
-
|
47
|
+
http.use_ssl = @url.scheme == 'https'
|
48
|
+
http.verify_mode = @ssl_verify_mode if @url.scheme == 'https'
|
49
|
+
resp = http.post(@url.request_uri, @outbuf, @headers)
|
50
|
+
data = resp.body
|
51
|
+
data = Bytes.force_binary_encoding(data)
|
47
52
|
@inbuf = StringIO.new data
|
48
|
-
@outbuf =
|
53
|
+
@outbuf = Bytes.empty_byte_buffer
|
49
54
|
end
|
50
55
|
end
|
51
56
|
end
|
@@ -32,7 +32,7 @@ module Thrift
|
|
32
32
|
|
33
33
|
def open?; not @input.closed? or not @output.closed? end
|
34
34
|
def read(sz); @input.read(sz) end
|
35
|
-
def write(buf); @output.write(buf) end
|
35
|
+
def write(buf); @output.write(Bytes.force_binary_encoding(buf)) end
|
36
36
|
def close; @input.close; @output.close end
|
37
37
|
def to_io; @input end # we're assuming this is used in a IO.select for reading
|
38
38
|
end
|
@@ -28,7 +28,7 @@ module Thrift
|
|
28
28
|
# this behavior is no longer required. If you wish to change it
|
29
29
|
# go ahead, just make sure the specs pass
|
30
30
|
def initialize(buffer = nil)
|
31
|
-
@buf = buffer
|
31
|
+
@buf = buffer ? Bytes.force_binary_encoding(buffer) : Bytes.empty_byte_buffer
|
32
32
|
@index = 0
|
33
33
|
end
|
34
34
|
|
@@ -48,7 +48,7 @@ module Thrift
|
|
48
48
|
|
49
49
|
# this method does not use the passed object directly but copies it
|
50
50
|
def reset_buffer(new_buf = '')
|
51
|
-
@buf.replace new_buf
|
51
|
+
@buf.replace Bytes.force_binary_encoding(new_buf)
|
52
52
|
@index = 0
|
53
53
|
end
|
54
54
|
|
@@ -72,7 +72,7 @@ module Thrift
|
|
72
72
|
|
73
73
|
def read_byte
|
74
74
|
raise EOFError.new("Not enough bytes remain in buffer") if @index >= @buf.size
|
75
|
-
val =
|
75
|
+
val = Bytes.get_string_byte(@buf, @index)
|
76
76
|
@index += 1
|
77
77
|
if @index >= GARBAGE_BUFFER_SIZE
|
78
78
|
@buf = @buf.slice(@index..-1)
|
@@ -87,8 +87,8 @@ module Thrift
|
|
87
87
|
raise EOFError.new("Not enough bytes remain in buffer") if @index >= @buf.size
|
88
88
|
|
89
89
|
# The read buffer has some data now, so copy bytes over to the output buffer.
|
90
|
-
byte =
|
91
|
-
|
90
|
+
byte = Bytes.get_string_byte(@buf, @index)
|
91
|
+
Bytes.set_string_byte(buffer, i, byte)
|
92
92
|
@index += 1
|
93
93
|
i += 1
|
94
94
|
end
|
@@ -100,7 +100,7 @@ module Thrift
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def write(wbuf)
|
103
|
-
@buf << wbuf
|
103
|
+
@buf << Bytes.force_binary_encoding(wbuf)
|
104
104
|
end
|
105
105
|
|
106
106
|
def flush
|