thrift 0.9.0 → 0.9.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.
Files changed (42) hide show
  1. checksums.yaml +15 -0
  2. data/ext/binary_protocol_accelerated.c +19 -3
  3. data/ext/compact_protocol.c +21 -7
  4. data/ext/constants.h +1 -5
  5. data/ext/extconf.rb +1 -1
  6. data/ext/protocol.c +0 -185
  7. data/ext/protocol.h +0 -20
  8. data/ext/struct.c +0 -3
  9. data/ext/thrift_native.c +1 -11
  10. data/lib/thrift.rb +1 -0
  11. data/lib/thrift/exceptions.rb +3 -0
  12. data/lib/thrift/protocol/base_protocol.rb +87 -10
  13. data/lib/thrift/protocol/binary_protocol.rb +13 -5
  14. data/lib/thrift/protocol/compact_protocol.rb +14 -7
  15. data/lib/thrift/protocol/json_protocol.rb +19 -15
  16. data/lib/thrift/server/mongrel_http_server.rb +2 -0
  17. data/lib/thrift/server/thin_http_server.rb +91 -0
  18. data/lib/thrift/struct.rb +1 -1
  19. data/lib/thrift/struct_union.rb +2 -2
  20. data/lib/thrift/transport/http_client_transport.rb +4 -1
  21. data/spec/base_protocol_spec.rb +65 -7
  22. data/spec/binary_protocol_spec_shared.rb +30 -0
  23. data/spec/compact_protocol_spec.rb +1 -3
  24. data/spec/http_client_spec.rb +49 -0
  25. data/spec/json_protocol_spec.rb +2 -2
  26. data/spec/thin_http_server_spec.rb +140 -0
  27. data/spec/union_spec.rb +13 -1
  28. metadata +113 -93
  29. data/benchmark/gen-rb/benchmark_constants.rb +0 -11
  30. data/benchmark/gen-rb/benchmark_service.rb +0 -80
  31. data/benchmark/gen-rb/benchmark_types.rb +0 -10
  32. data/spec/gen-rb/nonblocking_service.rb +0 -272
  33. data/spec/gen-rb/thrift_spec_constants.rb +0 -11
  34. data/spec/gen-rb/thrift_spec_types.rb +0 -538
  35. data/spec/mongrel_http_server_spec.rb +0 -114
  36. data/test/debug_proto/gen-rb/debug_proto_test_constants.rb +0 -274
  37. data/test/debug_proto/gen-rb/debug_proto_test_types.rb +0 -761
  38. data/test/debug_proto/gen-rb/empty_service.rb +0 -24
  39. data/test/debug_proto/gen-rb/inherited.rb +0 -79
  40. data/test/debug_proto/gen-rb/reverse_order_service.rb +0 -82
  41. data/test/debug_proto/gen-rb/service_for_exception_with_a_map.rb +0 -81
  42. data/test/debug_proto/gen-rb/srv.rb +0 -330
@@ -62,5 +62,6 @@ require 'thrift/server/nonblocking_server'
62
62
  require 'thrift/server/simple_server'
63
63
  require 'thrift/server/threaded_server'
64
64
  require 'thrift/server/thread_pool_server'
65
+ require 'thrift/server/thin_http_server'
65
66
 
66
67
  require 'thrift/thrift_native'
@@ -37,6 +37,9 @@ module Thrift
37
37
  MISSING_RESULT = 5
38
38
  INTERNAL_ERROR = 6
39
39
  PROTOCOL_ERROR = 7
40
+ INVALID_TRANSFORM = 8
41
+ INVALID_PROTOCOL = 9
42
+ UNSUPPORTED_CLIENT_TYPE = 10
40
43
 
41
44
  attr_reader :type
42
45
 
@@ -125,6 +125,16 @@ module Thrift
125
125
  raise NotImplementedError
126
126
  end
127
127
 
128
+ # Writes a Thrift Binary (Thrift String with no encoding). In Ruby 1.9+, the String passed
129
+ # will forced into BINARY encoding.
130
+ #
131
+ # buf - The String to write.
132
+ #
133
+ # Returns nothing.
134
+ def write_binary(buf)
135
+ raise NotImplementedError
136
+ end
137
+
128
138
  def read_message_begin
129
139
  raise NotImplementedError
130
140
  end
@@ -185,21 +195,67 @@ module Thrift
185
195
  raise NotImplementedError
186
196
  end
187
197
 
188
- # Reads a Thrift String. In Ruby 1.9+, all String will be returned with an Encoding of UTF-8.
198
+ # Reads a Thrift String. In Ruby 1.9+, all Strings will be returned with an Encoding of UTF-8.
189
199
  #
190
200
  # Returns a String.
191
201
  def read_string
192
202
  raise NotImplementedError
193
203
  end
194
204
 
195
- def write_field(name, type, fid, value)
196
- write_field_begin(name, type, fid)
197
- write_type(type, value)
205
+ # Reads a Thrift Binary (Thrift String without encoding). In Ruby 1.9+, all Strings will be returned
206
+ # with an Encoding of BINARY.
207
+ #
208
+ # Returns a String.
209
+ def read_binary
210
+ raise NotImplementedError
211
+ end
212
+
213
+ # Writes a field based on the field information, field ID and value.
214
+ #
215
+ # field_info - A Hash containing the definition of the field:
216
+ # :name - The name of the field.
217
+ # :type - The type of the field, which must be a Thrift::Types constant.
218
+ # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
219
+ # fid - The ID of the field.
220
+ # value - The field's value to write; object type varies based on :type.
221
+ #
222
+ # Returns nothing.
223
+ def write_field(*args)
224
+ if args.size == 3
225
+ # handles the documented method signature - write_field(field_info, fid, value)
226
+ field_info = args[0]
227
+ fid = args[1]
228
+ value = args[2]
229
+ elsif args.size == 4
230
+ # handles the deprecated method signature - write_field(name, type, fid, value)
231
+ field_info = {:name => args[0], :type => args[1]}
232
+ fid = args[2]
233
+ value = args[3]
234
+ else
235
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 3)"
236
+ end
237
+
238
+ write_field_begin(field_info[:name], field_info[:type], fid)
239
+ write_type(field_info, value)
198
240
  write_field_end
199
241
  end
200
242
 
201
- def write_type(type, value)
202
- case type
243
+ # Writes a field value based on the field information.
244
+ #
245
+ # field_info - A Hash containing the definition of the field:
246
+ # :type - The Thrift::Types constant that determines how the value is written.
247
+ # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
248
+ # value - The field's value to write; object type varies based on field_info[:type].
249
+ #
250
+ # Returns nothing.
251
+ def write_type(field_info, value)
252
+ # if field_info is a Fixnum, assume it is a Thrift::Types constant
253
+ # convert it into a field_info Hash for backwards compatibility
254
+ if field_info.is_a? Fixnum
255
+ field_info = {:type => field_info}
256
+ end
257
+
258
+ case field_info[:type]
203
259
  when Types::BOOL
204
260
  write_bool(value)
205
261
  when Types::BYTE
@@ -213,7 +269,11 @@ module Thrift
213
269
  when Types::I64
214
270
  write_i64(value)
215
271
  when Types::STRING
216
- write_string(value)
272
+ if field_info[:binary]
273
+ write_binary(value)
274
+ else
275
+ write_string(value)
276
+ end
217
277
  when Types::STRUCT
218
278
  value.write(self)
219
279
  else
@@ -221,8 +281,21 @@ module Thrift
221
281
  end
222
282
  end
223
283
 
224
- def read_type(type)
225
- case type
284
+ # Reads a field value based on the field information.
285
+ #
286
+ # field_info - A Hash containing the pertinent data to write:
287
+ # :type - The Thrift::Types constant that determines how the value is written.
288
+ # :binary - A flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
289
+ #
290
+ # Returns the value read; object type varies based on field_info[:type].
291
+ def read_type(field_info)
292
+ # if field_info is a Fixnum, assume it is a Thrift::Types constant
293
+ # convert it into a field_info Hash for backwards compatibility
294
+ if field_info.is_a? Fixnum
295
+ field_info = {:type => field_info}
296
+ end
297
+
298
+ case field_info[:type]
226
299
  when Types::BOOL
227
300
  read_bool
228
301
  when Types::BYTE
@@ -236,7 +309,11 @@ module Thrift
236
309
  when Types::I64
237
310
  read_i64
238
311
  when Types::STRING
239
- read_string
312
+ if field_info[:binary]
313
+ read_binary
314
+ else
315
+ read_string
316
+ end
240
317
  else
241
318
  raise NotImplementedError
242
319
  end
@@ -107,9 +107,13 @@ module Thrift
107
107
  end
108
108
 
109
109
  def write_string(str)
110
- str = Bytes.convert_to_utf8_byte_buffer(str)
111
- write_i32(str.length)
112
- trans.write(str)
110
+ buf = Bytes.convert_to_utf8_byte_buffer(str)
111
+ write_binary(buf)
112
+ end
113
+
114
+ def write_binary(buf)
115
+ write_i32(buf.bytesize)
116
+ trans.write(buf)
113
117
  end
114
118
 
115
119
  def read_message_begin
@@ -214,11 +218,15 @@ module Thrift
214
218
  end
215
219
 
216
220
  def read_string
217
- size = read_i32
218
- buffer = trans.read_all(size)
221
+ buffer = read_binary
219
222
  Bytes.convert_to_string(buffer)
220
223
  end
221
224
 
225
+ def read_binary
226
+ size = read_i32
227
+ trans.read_all(size)
228
+ end
229
+
222
230
  end
223
231
 
224
232
  class BinaryProtocolFactory < BaseProtocolFactory
@@ -210,9 +210,13 @@ module Thrift
210
210
  end
211
211
 
212
212
  def write_string(str)
213
- str = Bytes.convert_to_utf8_byte_buffer(str)
214
- write_varint32(str.length)
215
- @trans.write(str)
213
+ buf = Bytes.convert_to_utf8_byte_buffer(str)
214
+ write_binary(buf)
215
+ end
216
+
217
+ def write_binary(buf)
218
+ write_varint32(buf.bytesize)
219
+ @trans.write(buf)
216
220
  end
217
221
 
218
222
  def read_message_begin
@@ -332,12 +336,15 @@ module Thrift
332
336
  end
333
337
 
334
338
  def read_string
335
- size = read_varint32()
336
- buffer = trans.read_all(size)
339
+ buffer = read_binary
337
340
  Bytes.convert_to_string(buffer)
338
341
  end
339
-
340
-
342
+
343
+ def read_binary
344
+ size = read_varint32()
345
+ trans.read_all(size)
346
+ end
347
+
341
348
  private
342
349
 
343
350
  #
@@ -18,21 +18,6 @@
18
18
  # under the License.
19
19
  #
20
20
 
21
- @@kJSONObjectStart = '{'
22
- @@kJSONObjectEnd = '}'
23
- @@kJSONArrayStart = '['
24
- @@kJSONArrayEnd = ']'
25
- @@kJSONNewline = '\n'
26
- @@kJSONElemSeparator = ','
27
- @@kJSONPairSeparator = ':'
28
- @@kJSONBackslash = '\\'
29
- @@kJSONStringDelimiter = '"'
30
-
31
- @@kThriftVersion1 = 1
32
-
33
- @@kThriftNan = "NaN"
34
- @@kThriftInfinity = "Infinity"
35
- @@kThriftNegativeInfinity = "-Infinity"
36
21
 
37
22
  module Thrift
38
23
  class LookaheadReader
@@ -66,6 +51,7 @@ module Thrift
66
51
  # implementations
67
52
  #
68
53
  class JSONContext
54
+ @@kJSONElemSeparator = ','
69
55
  #
70
56
  # Write context data to the trans. Default is to do nothing.
71
57
  #
@@ -89,6 +75,8 @@ module Thrift
89
75
 
90
76
  # Context class for object member key-value pairs
91
77
  class JSONPairContext < JSONContext
78
+ @@kJSONPairSeparator = ':'
79
+
92
80
  def initialize
93
81
  @first = true
94
82
  @colon = true
@@ -146,6 +134,21 @@ module Thrift
146
134
  end
147
135
 
148
136
  class JsonProtocol < BaseProtocol
137
+
138
+ @@kJSONObjectStart = '{'
139
+ @@kJSONObjectEnd = '}'
140
+ @@kJSONArrayStart = '['
141
+ @@kJSONArrayEnd = ']'
142
+ @@kJSONNewline = '\n'
143
+ @@kJSONBackslash = '\\'
144
+ @@kJSONStringDelimiter = '"'
145
+
146
+ @@kThriftVersion1 = 1
147
+
148
+ @@kThriftNan = "NaN"
149
+ @@kThriftInfinity = "Infinity"
150
+ @@kThriftNegativeInfinity = "-Infinity"
151
+
149
152
  def initialize(trans)
150
153
  super(trans)
151
154
  @context = JSONContext.new
@@ -717,6 +720,7 @@ module Thrift
717
720
 
718
721
  def read_set_begin
719
722
  read_json_array_start
723
+ [get_type_id_for_type_name(read_json_string), read_json_integer]
720
724
  end
721
725
 
722
726
  def read_set_end
@@ -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
@@ -105,7 +105,7 @@ module Thrift
105
105
  write_container(oprot, value, field_info)
106
106
  oprot.write_field_end
107
107
  else
108
- oprot.write_field(name, type, fid, value)
108
+ oprot.write_field(field_info, fid, value)
109
109
  end
110
110
  end
111
111
  end
@@ -101,7 +101,7 @@ module Thrift
101
101
  end
102
102
  iprot.read_set_end
103
103
  else
104
- value = iprot.read_type(field[:type])
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[:type], value)
113
+ oprot.write_type(field, value)
114
114
  end
115
115
  end
116
116
 
@@ -20,16 +20,18 @@
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
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
@@ -43,6 +45,7 @@ module Thrift
43
45
  def flush
44
46
  http = Net::HTTP.new @url.host, @url.port
45
47
  http.use_ssl = @url.scheme == 'https'
48
+ http.verify_mode = @ssl_verify_mode if @url.scheme == 'https'
46
49
  resp = http.post(@url.request_uri, @outbuf, @headers)
47
50
  data = resp.body
48
51
  data = Bytes.force_binary_encoding(data)