thrift 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
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)