File: form_data.rb

package info (click to toggle)
ruby-http-form-data 1.0.1%2Bgemwatch-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 176 kB
  • ctags: 46
  • sloc: ruby: 366; makefile: 3
file content (76 lines) | stat: -rw-r--r-- 2,212 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
require "http/form_data/file"
require "http/form_data/multipart"
require "http/form_data/urlencoded"
require "http/form_data/version"

# http.rb namespace.
# @see https://github.com/httprb/http.rb
module HTTP
  # Utility-belt to build form data request bodies.
  # Provides support for `application/x-www-form-urlencoded` and
  # `multipart/form-data` types.
  #
  # @example Usage
  #
  #   form = FormData.create({
  #     :username     => "ixti",
  #     :avatar_file  => FormData::File.new("/home/ixti/avatar.png")
  #   })
  #
  #   # Assuming socket is an open socket to some HTTP server
  #   socket << "POST /some-url HTTP/1.1\r\n"
  #   socket << "Host: example.com\r\n"
  #   socket << "Content-Type: #{form.content_type}\r\n"
  #   socket << "Content-Length: #{form.content_length}\r\n"
  #   socket << "\r\n"
  #   socket << form.to_s
  module FormData
    # CRLF
    CRLF = "\r\n".freeze

    # Generic FormData error.
    class Error < StandardError; end

    class << self
      # FormData factory. Automatically selects best type depending on given
      # `data` Hash.
      #
      # @param [#to_h, Hash] data
      # @return [Multipart] if any of values is a {FormData::File}
      # @return [Urlencoded] otherwise
      def create(data)
        data  = ensure_hash data
        klass = multipart?(data) ? Multipart : Urlencoded

        klass.new data
      end

      # Coerce `obj` to Hash.
      #
      # @note Internal usage helper, to workaround lack of `#to_h` on Ruby < 2.1
      # @raise [Error] `obj` can't be coerced.
      # @return [Hash]
      def ensure_hash(obj)
        case
        when obj.nil?               then {}
        when obj.is_a?(Hash)        then obj
        when obj.respond_to?(:to_h) then obj.to_h
        else fail Error, "#{obj.inspect} is neither Hash nor responds to :to_h"
        end
      end

      private

      # Tells whenever data contains multipart data or not.
      #
      # @param [Hash] data
      # @return [Boolean]
      def multipart?(data)
        data.any? do |_, v|
          next true if v.is_a? FormData::File
          v.respond_to?(:to_ary) && v.to_ary.any? { |e| e.is_a? FormData::File }
        end
      end
    end
  end
end