troelskn-handsoap 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/VERSION.yml +1 -1
  2. data/lib/handsoap/service.rb +130 -5
  3. metadata +4 -4
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 4
3
- :patch: 1
3
+ :patch: 2
4
4
  :major: 0
@@ -189,12 +189,28 @@ module Handsoap
189
189
  on_after_create_http_client(http_client)
190
190
  http_client.headers = headers
191
191
  http_client.http_post post_body
192
- return { :status => http_client.response_code, :body => http_client.body_str, :content_type => http_client.content_type }
192
+ if %r|\Amultipart.*boundary=\"?([^\";,]+)\"?|n.match(http_client.content_type)
193
+ boundary = $1.dup
194
+ parts = Handsoap.parse_multipart(boundary, http_client.body_str)
195
+ is_multipart = true
196
+ else
197
+ parts = [{:head => http_client.header_str, :body => http_client.body_str}]
198
+ is_multipart = false
199
+ end
200
+ return { :status => http_client.response_code, :body => http_client.body_str, :content_type => http_client.content_type, :parts => parts, :multipart => is_multipart }
193
201
  elsif Handsoap.http_driver == :httpclient
194
202
  http_client = HTTPClient.new
195
203
  on_after_create_http_client(http_client)
196
204
  response = http_client.post(uri, post_body, headers)
197
- return { :status => response.status, :body => response.content, :content_type => response.contenttype }
205
+ if %r|\Amultipart.*boundary=\"?([^\";,]+)\"?|n.match(response.contenttype)
206
+ boundary = $1.dup
207
+ parts = Handsoap.parse_multipart(boundary, response.content)
208
+ is_multipart = true
209
+ else
210
+ parts = [{:head => response.all.join("\r\n"), :body => response.content}]
211
+ is_multipart = false
212
+ end
213
+ return { :status => response.status, :body => response.content, :content_type => response.contenttype, :parts => parts, :multipart => is_multipart }
198
214
  else
199
215
  raise "Unknown http driver #{Handsoap.http_driver}"
200
216
  end
@@ -220,12 +236,23 @@ module Handsoap
220
236
  logger.puts "--- Response ---"
221
237
  logger.puts "HTTP Status: %s" % [response[:status]]
222
238
  logger.puts "Content-Type: %s" % [response[:content_type]]
223
- logger.puts "---"
224
- logger.puts Handsoap.pretty_format_envelope(response[:body])
239
+ if response[:multipart]
240
+ num = 0
241
+ response[:parts].each do |part|
242
+ num += 1
243
+ logger.puts "--- Part ##{num} ---"
244
+ logger.puts part[:head].gsub(/\r\n/, "\n")
245
+ logger.puts "---"
246
+ logger.puts Handsoap.pretty_format_envelope(part[:body])
247
+ end
248
+ else
249
+ logger.puts "---"
250
+ logger.puts Handsoap.pretty_format_envelope(response[:body])
251
+ end
225
252
  end
226
253
  # Start the parsing pipe-line.
227
254
  # There are various stages and hooks for each, so that you can override those in your service classes.
228
- xml_document = parse_soap_response_document(response[:body])
255
+ xml_document = parse_soap_response_document(response[:parts].first[:body]) # Strictly speaking, the main part doesn't need to be first, but until proven otherwise, we'll just assume that.
229
256
  soap_fault = parse_soap_fault(xml_document)
230
257
  # Is the response a soap-fault?
231
258
  unless soap_fault.nil?
@@ -245,6 +272,10 @@ module Handsoap
245
272
  def xml_document.document
246
273
  self
247
274
  end
275
+ # I should probably use a class for this response object instead ...
276
+ def xml_document.parts
277
+ response[:parts]
278
+ end
248
279
  return xml_document
249
280
  end
250
281
  # Creates a standard SOAP envelope and yields the +Body+ element.
@@ -293,6 +324,100 @@ module Handsoap
293
324
  return xml_string
294
325
  end
295
326
 
327
+ # Parses a multipart http-response body into parts.
328
+ # +boundary+ is a string of the boundary token.
329
+ # +content_io+ is either a string or an IO. If it's an IO, then content_length must be specified.
330
+ # +content_length+ (optional) is an integer, specifying the length of +content_io+
331
+ #
332
+ # This code is lifted from cgi.rb
333
+ #
334
+ def self.parse_multipart(boundary, content_io, content_length = nil)
335
+ if content_io.kind_of? String
336
+ content_length = content_io.length
337
+ content_io = StringIO.new(content_io, 'r')
338
+ elsif !(content_io.kind_of? IO) || content_length.nil?
339
+ raise "Second argument must be String or IO with content_length"
340
+ end
341
+
342
+ boundary = "--" + boundary
343
+ quoted_boundary = Regexp.quote(boundary, "n")
344
+ buf = ""
345
+ bufsize = 10 * 1024
346
+ boundary_end = ""
347
+
348
+ # start multipart/form-data
349
+ content_io.binmode if defined? content_io.binmode
350
+ boundary_size = boundary.size + "\r\n".size
351
+ content_length -= boundary_size
352
+ status = content_io.read(boundary_size)
353
+ if nil == status
354
+ raise EOFError, "no content body"
355
+ elsif boundary + "\r\n" != status
356
+ raise EOFError, "bad content body"
357
+ end
358
+
359
+ parts = []
360
+
361
+ loop do
362
+ head = nil
363
+ if 10240 < content_length
364
+ require "tempfile"
365
+ body = Tempfile.new("CGI")
366
+ else
367
+ begin
368
+ require "stringio"
369
+ body = StringIO.new
370
+ rescue LoadError
371
+ require "tempfile"
372
+ body = Tempfile.new("CGI")
373
+ end
374
+ end
375
+ body.binmode if defined? body.binmode
376
+
377
+ until head and /#{quoted_boundary}(?:\r\n|--)/n.match(buf)
378
+
379
+ if (not head) and /\r\n\r\n/n.match(buf)
380
+ buf = buf.sub(/\A((?:.|\n)*?\r\n)\r\n/n) do
381
+ head = $1.dup
382
+ ""
383
+ end
384
+ next
385
+ end
386
+
387
+ if head and ( ("\r\n" + boundary + "\r\n").size < buf.size )
388
+ body.print buf[0 ... (buf.size - ("\r\n" + boundary + "\r\n").size)]
389
+ buf[0 ... (buf.size - ("\r\n" + boundary + "\r\n").size)] = ""
390
+ end
391
+
392
+ c = if bufsize < content_length
393
+ content_io.read(bufsize)
394
+ else
395
+ content_io.read(content_length)
396
+ end
397
+ if c.nil? || c.empty?
398
+ raise EOFError, "bad content body"
399
+ end
400
+ buf.concat(c)
401
+ content_length -= c.size
402
+ end
403
+
404
+ buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do
405
+ body.print $1
406
+ if "--" == $2
407
+ content_length = -1
408
+ end
409
+ boundary_end = $2.dup
410
+ ""
411
+ end
412
+
413
+ parts << {:head => head, :body => body.string}
414
+ break if buf.size == 0
415
+ break if content_length == -1
416
+ end
417
+ raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/
418
+ parts
419
+ end
420
+
296
421
  end
297
422
 
298
423
  # Legacy/BC code here. This shouldn't be used in new applications.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: troelskn-handsoap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Troels Knak-Nielsen
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-31 00:00:00 -07:00
12
+ date: 2009-08-03 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -33,7 +33,7 @@ files:
33
33
  - lib/handsoap/service.rb
34
34
  - lib/handsoap/xml_mason.rb
35
35
  - lib/handsoap/xml_query_front.rb
36
- has_rdoc: false
36
+ has_rdoc: true
37
37
  homepage: http://github.com/troelskn/handsoap
38
38
  licenses:
39
39
  post_install_message:
@@ -62,7 +62,7 @@ requirements:
62
62
  rubyforge_project:
63
63
  rubygems_version: 1.3.5
64
64
  signing_key:
65
- specification_version: 3
65
+ specification_version: 2
66
66
  summary: Handsoap is a library for creating SOAP clients in Ruby
67
67
  test_files: []
68
68