fetch-api 0.1.0 → 0.2.0

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: d8968e4c64a4d0b5370aef72a78f1b4ac04096057deb92d1bc1a6dd14353b3cd
4
- data.tar.gz: 2b7cdf82b75cf2c2d51abd5693f1ad278242e4e93645779b0909bfa7fd62de7a
3
+ metadata.gz: ae66c4ee1f7d2b11e55480e6456be9eb78f5b1f6a2da0a22fb0cef1b4388328b
4
+ data.tar.gz: 2995e13999494f718966a8dc3f293342593a17f88a0c003b702243ae710492e2
5
5
  SHA512:
6
- metadata.gz: 39bfda51fed25d97acb41128134615980b4eb35357a790d76c79feb1bf57c06e7f2047e2908c530d346e1b051f79b1846cf01c912209d1be6cebb7d1eeaf88c1
7
- data.tar.gz: 42cd5a712cfe067f16e70482c6013162d2a29d76666d709d5032badc79a4202a9c474d1ba38dd19598657ae1b2b0d51f5de32ef49ce7395d6221ba1f7d752526
6
+ metadata.gz: 81683853c7d4e62b19dd0e4472b343958d656c361251239e160c44504b5671ba3b32078626433fd63f0be5a5a6290564cdc232f1db0a2c8dbbf462320b2102d8
7
+ data.tar.gz: ca6a9131aa1a4a3c504e74521b3c8244e89a66cc4f5e2e9bb27a7974352c910a7a869cd1ab96b531ccf694f3565e5ba93ae8de21d374006ac533ddb0f289241e
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Fetch API
1
+ # Fetch API for Ruby
2
2
 
3
3
  Ruby's Net::HTTP is very powerful, but has a complicated API. OpenURI is easy to use, but has limited functionality. Third-party HTTP clients each have different APIs, and it can sometimes be difficult to learn how to use them.
4
4
 
@@ -30,9 +30,11 @@ require 'fetch-api'
30
30
  res = Fetch::API.fetch('https://example.com')
31
31
 
32
32
  # res is a Rack::Response object
33
- puts res.body
33
+ puts res.body.first
34
34
  ```
35
35
 
36
+ or
37
+
36
38
  ``` ruby
37
39
  require 'fetch-api'
38
40
 
@@ -41,6 +43,13 @@ include Fetch::API
41
43
  res = fetch('https://example.com')
42
44
  ```
43
45
 
46
+ Supported options are as follows:
47
+
48
+ - `method`: HTTP method (default: `'GET'`)
49
+ - `headers`: Request headers (default: `{}`)
50
+ - `body`: Request body (default: `nil`)
51
+ - `redirect`: Follow redirects (one of `follow`, `error`, `manual`, default: `follow`)
52
+
44
53
  ### Post JSON
45
54
 
46
55
  ``` ruby
@@ -57,23 +66,30 @@ res = fetch('http://example.com', **{
57
66
  })
58
67
  ```
59
68
 
60
- ### Post Form
69
+ ### Post application/x-www-form-urlencoded
61
70
 
62
71
  ``` ruby
63
72
  res = fetch('http://example.com', **{
64
73
  method: 'POST',
65
74
 
66
- headers: {
67
- 'Content-Type' => 'multipart/form-data'
68
- },
69
-
70
- body: Rack::Multipart.build_multipart(
71
- file: Rack::Multipart::UploadedFile.new(io: StringIO.new('foo'), filename: 'foo.txt')
75
+ body: Fetch::URLSearchParams.new(
76
+ name: 'Alice'
72
77
  )
73
78
  })
74
79
  ```
75
80
 
76
- Note: `Rack::Multipart.build_multipart` returns nil if the parameter does not include UploadedFile.
81
+ ### Post multipart/form-data
82
+
83
+ ``` ruby
84
+ res = fetch('http://example.com', **{
85
+ method: 'POST',
86
+
87
+ body: Fetch::FormData.build(
88
+ name: 'Alice',
89
+ file: File.open('path/to/file.txt')
90
+ )
91
+ })
92
+ ```
77
93
 
78
94
  ## Development
79
95
 
data/lib/fetch/client.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  require_relative '../fetch'
2
+ require_relative 'form_data'
3
+ require_relative 'url_search_params'
2
4
 
5
+ require 'marcel'
3
6
  require 'net/http'
4
- require 'net/https'
5
7
  require 'rack/response'
6
8
  require 'singleton'
7
9
  require 'uri'
@@ -18,7 +20,25 @@ module Fetch
18
20
  req[k] = v
19
21
  end
20
22
 
21
- req.body = body
23
+ case body
24
+ when FormData
25
+ req.set_form body.entries.map {|k, v|
26
+ if v.is_a?(File)
27
+ [k, v, {
28
+ filename: File.basename(v.path),
29
+ content_type: Marcel::MimeType.for(v) || 'application/octet-stream'
30
+ }]
31
+ else
32
+ [k, v]
33
+ end
34
+ }, 'multipart/form-data'
35
+ when URLSearchParams
36
+ req['Content-Type'] ||= 'application/x-www-form-urlencoded'
37
+
38
+ req.body = body.to_s
39
+ else
40
+ req.body = body
41
+ end
22
42
 
23
43
  http = Net::HTTP.new(uri.hostname, uri.port)
24
44
  http.use_ssl = uri.scheme == 'https'
@@ -29,9 +49,9 @@ module Fetch
29
49
  when Net::HTTPRedirection
30
50
  case redirect
31
51
  when 'follow'
32
- fetch(res['location'], method:, headers:, body:, redirect:)
52
+ fetch(res['Location'], method:, headers:, body:, redirect:)
33
53
  when 'error'
34
- raise RedirectError, "redirected to #{res['location']}"
54
+ raise RedirectError, "redirected to #{res['Location']}"
35
55
  when 'manual'
36
56
  to_rack_response(res)
37
57
  else
@@ -0,0 +1,60 @@
1
+ module Fetch
2
+ class FormData
3
+ include Enumerable
4
+
5
+ def self.build(enumerable)
6
+ data = FormData.new
7
+
8
+ enumerable.each do |k, v|
9
+ data.append k, v
10
+ end
11
+
12
+ data
13
+ end
14
+
15
+ def initialize
16
+ @entries = []
17
+ end
18
+
19
+ attr_reader :entries
20
+
21
+ def append(key, value)
22
+ @entries.push [key.to_s, value]
23
+ end
24
+
25
+ def delete(key)
26
+ @entries.reject! {|k,| k == key.to_s }
27
+ end
28
+
29
+ def get(key)
30
+ @entries.assoc(key.to_s)&.last
31
+ end
32
+
33
+ def get_all(key)
34
+ @entries.select {|k,| k == key.to_s }.map(&:last)
35
+ end
36
+
37
+ def has(key)
38
+ @entries.any? {|k,| k == key.to_s }
39
+ end
40
+
41
+ def keys
42
+ @entries.map(&:first)
43
+ end
44
+
45
+ def set(key, value)
46
+ delete key
47
+ append key, value
48
+ end
49
+
50
+ def values
51
+ @entries.map(&:last)
52
+ end
53
+
54
+ def each(&block)
55
+ return enum_for(:each) unless block_given?
56
+
57
+ @entries.each(&block)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,71 @@
1
+ require 'uri'
2
+
3
+ module Fetch
4
+ class URLSearchParams
5
+ include Enumerable
6
+
7
+ def initialize(options = [])
8
+ @entries = []
9
+
10
+ case options
11
+ when String
12
+ initialize(URI.decode_www_form(options.delete_prefix('?')))
13
+ when Enumerable
14
+ options.each do |k, v|
15
+ append k, v
16
+ end
17
+ else
18
+ raise ArgumentError
19
+ end
20
+ end
21
+
22
+ attr_reader :entries
23
+
24
+ def append(key, value)
25
+ @entries.push [key.to_s, value]
26
+ end
27
+
28
+ def delete(key)
29
+ @entries.reject! {|k,| k == key.to_s }
30
+ end
31
+
32
+ def get(key)
33
+ @entries.assoc(key.to_s)&.last
34
+ end
35
+
36
+ def get_all(key)
37
+ @entries.select {|k,| k == key.to_s }.map(&:last)
38
+ end
39
+
40
+ def has(key)
41
+ @entries.any? {|k,| k == key.to_s }
42
+ end
43
+
44
+ def keys
45
+ @entries.map(&:first)
46
+ end
47
+
48
+ def set(key, value)
49
+ delete key
50
+ append key, value
51
+ end
52
+
53
+ def sort
54
+ @entries.sort_by!(&:first)
55
+ end
56
+
57
+ def to_s
58
+ URI.encode_www_form(@entries)
59
+ end
60
+
61
+ def values
62
+ @entries.map(&:last)
63
+ end
64
+
65
+ def each(&block)
66
+ return enum_for(:each) unless block_given?
67
+
68
+ @entries.each(&block)
69
+ end
70
+ end
71
+ end
data/lib/fetch/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fetch
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/fetch.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require_relative 'fetch/version'
2
- require_relative 'fetch/api'
3
2
 
4
3
  module Fetch
5
4
  class Error < StandardError; end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fetch-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keita Urashima
@@ -10,6 +10,20 @@ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2024-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: marcel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: net-http
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -79,6 +93,8 @@ files:
79
93
  - lib/fetch.rb
80
94
  - lib/fetch/api.rb
81
95
  - lib/fetch/client.rb
96
+ - lib/fetch/form_data.rb
97
+ - lib/fetch/url_search_params.rb
82
98
  - lib/fetch/version.rb
83
99
  - sig/fetch.rbs
84
100
  homepage: https://github.com/ursm/fetch-api