fast_curl 0.3.0 → 0.4.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 +4 -4
- data/README.md +91 -11
- data/ext/fast_curl/extconf.rb +3 -0
- data/ext/fast_curl/fast_curl.c +1151 -359
- data/lib/fast_curl/version.rb +1 -1
- data/lib/fast_curl.rb +114 -6
- metadata +37 -27
data/lib/fast_curl/version.rb
CHANGED
data/lib/fast_curl.rb
CHANGED
|
@@ -1,13 +1,75 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
|
+
require 'uri'
|
|
4
5
|
require_relative "fast_curl/version"
|
|
5
|
-
require_relative "fast_curl/fast_curl"
|
|
6
6
|
|
|
7
7
|
module FastCurl
|
|
8
8
|
class Error < StandardError; end
|
|
9
9
|
class TimeoutError < Error; end
|
|
10
10
|
|
|
11
|
+
class Headers < Hash
|
|
12
|
+
def [](key)
|
|
13
|
+
super(normalize(key))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def []=(key, value)
|
|
17
|
+
super(normalize(key), value)
|
|
18
|
+
end
|
|
19
|
+
alias store []=
|
|
20
|
+
|
|
21
|
+
def fetch(key, *args, &block)
|
|
22
|
+
super(normalize(key), *args, &block)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def key?(key)
|
|
26
|
+
super(normalize(key))
|
|
27
|
+
end
|
|
28
|
+
alias has_key? key?
|
|
29
|
+
alias include? key?
|
|
30
|
+
alias member? key?
|
|
31
|
+
|
|
32
|
+
def delete(key, &block)
|
|
33
|
+
super(normalize(key), &block)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def dig(key, *rest)
|
|
37
|
+
super(normalize(key), *rest)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def values_at(*keys)
|
|
41
|
+
super(*keys.map { |key| normalize(key) })
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def assoc(key)
|
|
45
|
+
super(normalize(key))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def merge(*others, &block)
|
|
49
|
+
others.inject(dup) { |acc, other| acc.merge!(other, &block) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def merge!(*others)
|
|
53
|
+
others.each do |other|
|
|
54
|
+
other.each do |key, value|
|
|
55
|
+
self[key] = block_given? && key?(key) ? yield(normalize(key), self[key], value) : value
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
self
|
|
59
|
+
end
|
|
60
|
+
alias update merge!
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def normalize(key)
|
|
65
|
+
key.is_a?(String) || key.is_a?(Symbol) ? key.to_s.downcase : key
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
require_relative "fast_curl/fast_curl"
|
|
71
|
+
|
|
72
|
+
module FastCurl
|
|
11
73
|
DEFAULT_OPTIONS = {
|
|
12
74
|
connections: 20,
|
|
13
75
|
timeout: 30
|
|
@@ -16,6 +78,10 @@ module FastCurl
|
|
|
16
78
|
METHODS = %i[get post put delete patch].freeze
|
|
17
79
|
BODY_METHODS = %i[post put patch].freeze
|
|
18
80
|
|
|
81
|
+
JSON_TYPE = "application/json"
|
|
82
|
+
FORM_TYPE = "application/x-www-form-urlencoded"
|
|
83
|
+
BINARY_TYPE = "application/octet-stream"
|
|
84
|
+
|
|
19
85
|
class << self
|
|
20
86
|
METHODS.each do |method|
|
|
21
87
|
define_method(method) do |requests, **options|
|
|
@@ -35,14 +101,56 @@ module FastCurl
|
|
|
35
101
|
|
|
36
102
|
def build_requests(requests, method)
|
|
37
103
|
requests.map do |req|
|
|
38
|
-
r = { url: req
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
104
|
+
r = { url: build_url(req), method: method.to_s.upcase }
|
|
105
|
+
headers = req[:headers] ? req[:headers].dup : nil
|
|
106
|
+
|
|
107
|
+
if BODY_METHODS.include?(method)
|
|
108
|
+
body, content_type = build_body(req)
|
|
109
|
+
if body
|
|
110
|
+
r[:body] = body
|
|
111
|
+
if content_type && !content_type?(headers)
|
|
112
|
+
headers ||= {}
|
|
113
|
+
headers["Content-Type"] = content_type
|
|
114
|
+
end
|
|
115
|
+
end
|
|
43
116
|
end
|
|
117
|
+
|
|
118
|
+
r[:headers] = headers if headers && !headers.empty?
|
|
44
119
|
r
|
|
45
120
|
end
|
|
46
121
|
end
|
|
122
|
+
|
|
123
|
+
def build_url(req)
|
|
124
|
+
url = req[:url]
|
|
125
|
+
params = req[:params]
|
|
126
|
+
return url if params.nil? || params.empty? || !url.is_a?(String)
|
|
127
|
+
|
|
128
|
+
separator = url.include?("?") ? "&" : "?"
|
|
129
|
+
"#{url}#{separator}#{URI.encode_www_form(params)}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Returns [body_string, default_content_type].
|
|
133
|
+
# json: {...} or "..." -> application/json
|
|
134
|
+
# form: {...} -> application/x-www-form-urlencoded
|
|
135
|
+
# body: "..." -> application/octet-stream (set your own type)
|
|
136
|
+
# body: {...} -> application/json (kept for backwards compatibility)
|
|
137
|
+
def build_body(req)
|
|
138
|
+
if req.key?(:json)
|
|
139
|
+
value = req[:json]
|
|
140
|
+
[value.is_a?(String) ? value : value.to_json, JSON_TYPE]
|
|
141
|
+
elsif req.key?(:form)
|
|
142
|
+
value = req[:form]
|
|
143
|
+
[value.is_a?(String) ? value : URI.encode_www_form(value), FORM_TYPE]
|
|
144
|
+
elsif req.key?(:body) && !req[:body].nil?
|
|
145
|
+
value = req[:body]
|
|
146
|
+
value.is_a?(Hash) ? [value.to_json, JSON_TYPE] : [value.to_s, BINARY_TYPE]
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def content_type?(headers)
|
|
151
|
+
return false unless headers
|
|
152
|
+
|
|
153
|
+
headers.any? { |k, _| k.to_s.casecmp("content-type").zero? }
|
|
154
|
+
end
|
|
47
155
|
end
|
|
48
156
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fast_curl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- roman-haidarov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json
|
|
@@ -28,72 +28,82 @@ dependencies:
|
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '13.0'
|
|
34
|
+
- - "<"
|
|
35
|
+
- !ruby/object:Gem::Version
|
|
36
|
+
version: '14'
|
|
34
37
|
type: :development
|
|
35
38
|
prerelease: false
|
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
40
|
requirements:
|
|
38
|
-
- - "
|
|
41
|
+
- - ">="
|
|
39
42
|
- !ruby/object:Gem::Version
|
|
40
43
|
version: '13.0'
|
|
44
|
+
- - "<"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '14'
|
|
41
47
|
- !ruby/object:Gem::Dependency
|
|
42
48
|
name: rake-compiler
|
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
|
44
50
|
requirements:
|
|
45
|
-
- - "
|
|
51
|
+
- - ">="
|
|
46
52
|
- !ruby/object:Gem::Version
|
|
47
53
|
version: '1.2'
|
|
54
|
+
- - "<"
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '2'
|
|
48
57
|
type: :development
|
|
49
58
|
prerelease: false
|
|
50
59
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
60
|
requirements:
|
|
52
|
-
- - "
|
|
61
|
+
- - ">="
|
|
53
62
|
- !ruby/object:Gem::Version
|
|
54
63
|
version: '1.2'
|
|
64
|
+
- - "<"
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '2'
|
|
55
67
|
- !ruby/object:Gem::Dependency
|
|
56
68
|
name: minitest
|
|
57
69
|
requirement: !ruby/object:Gem::Requirement
|
|
58
70
|
requirements:
|
|
59
|
-
- - "
|
|
71
|
+
- - ">="
|
|
60
72
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '5.
|
|
62
|
-
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
73
|
+
version: '5.14'
|
|
74
|
+
- - "<"
|
|
67
75
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: benchmark-ips
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - "~>"
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '2.0'
|
|
76
|
+
version: '6'
|
|
76
77
|
type: :development
|
|
77
78
|
prerelease: false
|
|
78
79
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
80
|
requirements:
|
|
80
|
-
- - "
|
|
81
|
+
- - ">="
|
|
81
82
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
83
|
+
version: '5.14'
|
|
84
|
+
- - "<"
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '6'
|
|
83
87
|
- !ruby/object:Gem::Dependency
|
|
84
88
|
name: webrick
|
|
85
89
|
requirement: !ruby/object:Gem::Requirement
|
|
86
90
|
requirements:
|
|
87
|
-
- - "
|
|
91
|
+
- - ">="
|
|
88
92
|
- !ruby/object:Gem::Version
|
|
89
93
|
version: '1.8'
|
|
94
|
+
- - "<"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '2'
|
|
90
97
|
type: :development
|
|
91
98
|
prerelease: false
|
|
92
99
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
100
|
requirements:
|
|
94
|
-
- - "
|
|
101
|
+
- - ">="
|
|
95
102
|
- !ruby/object:Gem::Version
|
|
96
103
|
version: '1.8'
|
|
104
|
+
- - "<"
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: '2'
|
|
97
107
|
description: Parallel HTTP requests via libcurl curl_multi API. Releases GVL during
|
|
98
108
|
I/O, compatible with Async gem and Fiber scheduler. Supports execute (all), first_execute
|
|
99
109
|
(first N), stream_execute (yield as ready). Built-in retry functionality for network
|
|
@@ -123,14 +133,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
123
133
|
requirements:
|
|
124
134
|
- - ">="
|
|
125
135
|
- !ruby/object:Gem::Version
|
|
126
|
-
version:
|
|
136
|
+
version: 2.7.0
|
|
127
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
138
|
requirements:
|
|
129
139
|
- - ">="
|
|
130
140
|
- !ruby/object:Gem::Version
|
|
131
141
|
version: '0'
|
|
132
142
|
requirements: []
|
|
133
|
-
rubygems_version: 3.
|
|
143
|
+
rubygems_version: 3.4.22
|
|
134
144
|
signing_key:
|
|
135
145
|
specification_version: 4
|
|
136
146
|
summary: Ultra-fast parallel HTTP client as Ruby C extension on libcurl multi
|