flexirest 1.8.1 → 1.8.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c49db36f1d2d0003480f590b89099c921838b25acdca881383654ca88e1fe961
4
- data.tar.gz: 05ddbaf9a0ad3819f876585dfec4eeab53e7d746b9ac55ea7b8810a7fea5c3b9
3
+ metadata.gz: e5882e42d04af9b4712dd46b441168bb9977e8dd14e7e5a9bd870af567395b27
4
+ data.tar.gz: da50ac5d8b4e980767ac10d4e7b81e47cfaf6814646689d4cf221d08066c3718
5
5
  SHA512:
6
- metadata.gz: 7c51ca15f2502dfe13a5035fb6ab1566fde2b1bb32fdc5b946e7cae60fcbd778da085dbdc404e73a245312c4ad54e7f5f48161f625ffd130981f4a55a232f219
7
- data.tar.gz: b4216957e4ceea4255ca35375986c9fe98c8e865b79a2426b81d7268d1150a67c704615270dc429ffa07e60d6b114d9d5d93a33b75e9c45f9c4e8d9686a28d9d
6
+ metadata.gz: af1c263325803f45a3c6c79422eb97caee973b18d2ee492f5fdc6183d315817379815686a35caa71acd54f0fda0060b469bac9871c2a3258640eea4c19752e28
7
+ data.tar.gz: 5f06638ddf0978c0f908e5c79b2e34d0c24d0d362de0e9df2a972561f73dcede626a9947ac901caa612e175f05458fe40d279d881e19a6b22c0f69bac1c371fa
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.8.2
4
+
5
+ Features:
6
+
7
+ - Allowed use of `:form_multipart` as a `request_body_type` to allow uploading files to an API.
8
+
3
9
  ## 1.8.1
4
10
 
5
11
  Features:
@@ -17,6 +17,8 @@ Flexirest::Base.request_body_type = :json
17
17
 
18
18
  This will also set the header `Content-Type` to `application/x-www-form-urlencoded` by default or `application/json; charset=utf-8` when `:json`. You can override this using the callback `before_request`.
19
19
 
20
+ You can also use `:form_multipart` if your API requires file uploads. Any parameters set to `File` like object (supporting `#path` and `#read`) will be automatically uploaded with the parameters, in a normal form submission style.
21
+
20
22
  If you have an API that is inconsistent in its body type requirements, you can also specify it on the individual method mapping:
21
23
 
22
24
  ```ruby
@@ -13,6 +13,7 @@ require "flexirest/result_iterator"
13
13
  require "flexirest/headers_list"
14
14
  require "flexirest/lazy_loader"
15
15
  require "flexirest/lazy_association_loader"
16
+ require "flexirest/multipart"
16
17
  require "flexirest/json_api_proxy"
17
18
  require "flexirest/request"
18
19
  require "flexirest/request_delegator"
@@ -0,0 +1,81 @@
1
+ # Takes a hash of string and file parameters and returns a string of text
2
+ # formatted to be sent as a multipart form post.
3
+ #
4
+ # Author:: Cody Brimhall <mailto:brimhall@somuchwit.com>
5
+ # Created:: 22 Feb 2008
6
+ # License:: Distributed under the terms of the WTFPL (http://www.wtfpl.net/txt/copying/)
7
+
8
+ require 'rubygems'
9
+ require 'mime/types'
10
+ require 'cgi'
11
+
12
+
13
+ module Flexirest
14
+ module Multipart
15
+ VERSION = "1.0.0"
16
+
17
+ # Formats a given hash as a multipart form post
18
+ # If a hash value responds to :string or :read messages, then it is
19
+ # interpreted as a file and processed accordingly; otherwise, it is assumed
20
+ # to be a string
21
+ class Post
22
+ BOUNDARY = "FLEXIRESTBOUNDARY-20190918-FLEXIRESTBOUNDARY"
23
+ CONTENT_TYPE = "multipart/form-data; boundary=#{BOUNDARY}"
24
+ HEADER = {"Content-Type" => CONTENT_TYPE}
25
+
26
+ def self.prepare_query(params)
27
+ fp = []
28
+
29
+ params.stringify_keys.each do |k, v|
30
+ # Are we trying to make a file parameter?
31
+ if v.respond_to?(:path) and v.respond_to?(:read) then
32
+ fp.push(FileParam.new(k, v.path, v.read))
33
+ # We must be trying to make a regular parameter
34
+ else
35
+ fp.push(StringParam.new(k, v))
36
+ end
37
+ end
38
+
39
+ # Assemble the request body using the special multipart format
40
+ query = fp.collect {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("") + "--" + BOUNDARY + "--"
41
+ return query, HEADER
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # Formats a basic string key/value pair for inclusion with a multipart post
48
+ class StringParam
49
+ attr_accessor :k, :v
50
+
51
+ def initialize(k, v)
52
+ @k = k
53
+ @v = v
54
+ end
55
+
56
+ def to_multipart
57
+ return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n"
58
+ end
59
+ end
60
+
61
+ # Formats the contents of a file or string for inclusion with a multipart
62
+ # form post
63
+ class FileParam
64
+ attr_accessor :k, :filename, :content
65
+
66
+ def initialize(k, filename, content)
67
+ @k = k
68
+ @filename = filename
69
+ @content = content
70
+ end
71
+
72
+ def to_multipart
73
+ # If we can tell the possible mime-type from the filename, use the
74
+ # first in the list; otherwise, use "application/octet-stream"
75
+ mime_type = MIME::Types.type_for(filename)[0] || MIME::Types["application/octet-stream"][0]
76
+ return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"; filename=\"#{ filename }\"\r\n" +
77
+ "Content-Type: #{ mime_type.simplified }\r\n\r\n#{ content }\r\n"
78
+ end
79
+ end
80
+ end
81
+ end
@@ -400,6 +400,8 @@ module Flexirest
400
400
  elsif http_method == :get || (http_method == :delete && !@method[:options][:send_delete_body])
401
401
  if request_body_type == :form_encoded
402
402
  headers["Content-Type"] ||= "application/x-www-form-urlencoded; charset=utf-8"
403
+ elsif request_body_type == :form_multipart
404
+ headers["Content-Type"] ||= "multipart/form-data; charset=utf-8"
403
405
  elsif request_body_type == :json
404
406
  headers["Content-Type"] ||= "application/json; charset=utf-8"
405
407
  end
@@ -417,6 +419,23 @@ module Flexirest
417
419
  p.to_query
418
420
  end
419
421
  headers["Content-Type"] ||= "application/x-www-form-urlencoded"
422
+ elsif request_body_type == :form_multipart
423
+ headers["Content-Type"] ||= "multipart/form-data; charset=utf-8"
424
+ @body ||= if params.is_a?(String)
425
+ params
426
+ elsif @post_params.is_a?(String)
427
+ @post_params
428
+ else
429
+ p = (params || @post_params || {})
430
+ if @method[:options][:wrap_root].present?
431
+ p = {@method[:options][:wrap_root] => p}
432
+ end
433
+ data, mp_headers = Flexirest::Multipart::Post.prepare_query(p)
434
+ mp_headers.each do |k,v|
435
+ headers[k] = v
436
+ end
437
+ data
438
+ end
420
439
  elsif request_body_type == :json
421
440
  @body ||= if params.is_a?(String)
422
441
  params
@@ -1,3 +1,3 @@
1
1
  module Flexirest
2
- VERSION = "1.8.1"
2
+ VERSION = "1.8.2"
3
3
  end
@@ -353,6 +353,28 @@ describe Flexirest::Request do
353
353
  ExampleClient.update id:1234, debug:true, test:'foo'
354
354
  end
355
355
 
356
+ it "should encode the body in a form-encoded format by default" do
357
+ body = "--FLEXIRESTBOUNDARY-20190918-FLEXIRESTBOUNDARY\r\n" +
358
+ "Content-Disposition: form-data; name=\"debug\"\r\n" +
359
+ "\r\n" +
360
+ "true\r\n" +
361
+ "--FLEXIRESTBOUNDARY-20190918-FLEXIRESTBOUNDARY\r\n" +
362
+ "Content-Disposition: form-data; name=\"test\"\r\n" +
363
+ "\r\n" +
364
+ "foo\r\n" +
365
+ "--FLEXIRESTBOUNDARY-20190918-FLEXIRESTBOUNDARY\r\n" +
366
+ "Content-Disposition: form-data; name=\"file\"; filename=\"#{File.dirname(__FILE__)}/../../spec/samples/file.txt\"\r\n" +
367
+ "Content-Type: text/plain\r\n" +
368
+ "\r\n" +
369
+ "The quick brown fox jumps over the lazy dog\n\r\n" +
370
+ "--FLEXIRESTBOUNDARY-20190918-FLEXIRESTBOUNDARY--"
371
+ expect_any_instance_of(Flexirest::Connection).to receive(:put).with(
372
+ "/put/1234", body, hash_including(headers: hash_including("Content-Type"=>"multipart/form-data; boundary=FLEXIRESTBOUNDARY-20190918-FLEXIRESTBOUNDARY"))
373
+ ).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"result\":true}", response_headers:{})))
374
+ ExampleClient.request_body_type :form_multipart
375
+ ExampleClient.update id:1234, debug:true, test:'foo', file: File.open("#{File.dirname(__FILE__)}/../../spec/samples/file.txt")
376
+ end
377
+
356
378
  it "should encode the body in a JSON format if specified" do
357
379
  expect_any_instance_of(Flexirest::Connection).to receive(:put).with("/put/1234", %q({"debug":true,"test":"foo"}), an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"result\":true}", response_headers:{})))
358
380
  ExampleClient.request_body_type :json
@@ -0,0 +1 @@
1
+ The quick brown fox jumps over the lazy dog
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flexirest
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Jeffries
@@ -293,6 +293,7 @@ files:
293
293
  - lib/flexirest/logger.rb
294
294
  - lib/flexirest/mapping.rb
295
295
  - lib/flexirest/monkey_patching.rb
296
+ - lib/flexirest/multipart.rb
296
297
  - lib/flexirest/plain_response.rb
297
298
  - lib/flexirest/proxy_base.rb
298
299
  - lib/flexirest/recording.rb
@@ -327,6 +328,7 @@ files:
327
328
  - spec/lib/ruby_core_spec.rb
328
329
  - spec/lib/validation_spec.rb
329
330
  - spec/lib/xml_spec.rb
331
+ - spec/samples/file.txt
330
332
  - spec/spec_helper.rb
331
333
  homepage: https://andyjeffries.co.uk/
332
334
  licenses:
@@ -382,4 +384,5 @@ test_files:
382
384
  - spec/lib/ruby_core_spec.rb
383
385
  - spec/lib/validation_spec.rb
384
386
  - spec/lib/xml_spec.rb
387
+ - spec/samples/file.txt
385
388
  - spec/spec_helper.rb