yobi-http 0.14.0 → 0.16.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/exe/yobi +27 -5
- data/lib/yobi/cli/arguments.rb +35 -9
- data/lib/yobi/http.rb +21 -8
- data/lib/yobi/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3558906f242a7670158833610ad7b062bf25e308e4985804241bdba30a9d6968
|
|
4
|
+
data.tar.gz: d96e600ccdf03ebcddb0c9ce14a3a2c141fb1a1ba2ffe04ee7cdb0a1a5383c7d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 68ec04f8b731ebc0e9f508ed332d6414292963d1dbbd97aaba96a360e930ce3d1421812d11c1031305126633db9ad012fb2f4efa6e170aba4e09e3eeef37cf3e
|
|
7
|
+
data.tar.gz: 61c69a1bfdc761df2c791396fb84a3ce5183bf24b71ffb4073fbebdbd1e86b3e5e6986fbeeb977a7c2225624d72d083270e585e0afe186030066b3dab05f0e6c
|
data/exe/yobi
CHANGED
|
@@ -16,7 +16,7 @@ require "yobi"
|
|
|
16
16
|
# parsing arguments
|
|
17
17
|
@options = {
|
|
18
18
|
print: "HB", auth: nil, auth_type: "basic", verbose: false, raw: false, offline: false, follow: false, debug: false,
|
|
19
|
-
timeout: nil, download: false
|
|
19
|
+
timeout: nil, download: false, output: nil, content_type: :json
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
parser = OptionParser.new do |opts|
|
|
@@ -28,7 +28,7 @@ parser = OptionParser.new do |opts|
|
|
|
28
28
|
|
|
29
29
|
Examples:
|
|
30
30
|
yobi https://api.example.com/users
|
|
31
|
-
yobi POST https://api.example.com/
|
|
31
|
+
yobi POST https://api.example.com/products name="New Product" price:=19.99 enabled:=true tags:=@tags.json
|
|
32
32
|
yobi GET :8080/api/items Authorization:"Bearer $TOKEN"
|
|
33
33
|
yobi -A basic -a user:pass https://api.example.com/secure-data
|
|
34
34
|
yobi --raw --print B POST https://httpbin.org/anything | jq '.headers["User-Agent"]'
|
|
@@ -53,6 +53,27 @@ parser = OptionParser.new do |opts|
|
|
|
53
53
|
@options[:raw] = true
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
+
opts.on("--form", "Send data as application/x-www-form-urlencoded instead of JSON") do
|
|
57
|
+
@options[:content_type] = :form
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
opts.on("--multipart", "Send data as multipart/form-data instead of JSON") do
|
|
61
|
+
@options[:content_type] = :multipart
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
opts.on("--xml", "Send data as application/xml instead of JSON") do
|
|
65
|
+
@options[:content_type] = :xml
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
opts.on("--binary", "Send data as application/octet-stream instead of JSON") do
|
|
69
|
+
@options[:content_type] = :binary
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
opts.on("--json", "Send data as application/json (default)") do
|
|
73
|
+
# This option is implicit since JSON is the default, but we can set it explicitly if needed
|
|
74
|
+
@options[:content_type] = :json
|
|
75
|
+
end
|
|
76
|
+
|
|
56
77
|
opts.on("-h", "--help", "Print this help message") do
|
|
57
78
|
puts opts
|
|
58
79
|
exit
|
|
@@ -101,13 +122,14 @@ method = Yobi.args.http_method?(ARGV[0]) ? ARGV.shift : "GET"
|
|
|
101
122
|
# resolve the URL
|
|
102
123
|
url = Yobi.args.url(ARGV.shift)
|
|
103
124
|
|
|
104
|
-
data = Yobi.args.parse_data(ARGV)
|
|
105
|
-
|
|
125
|
+
data = Yobi.args.parse_data(ARGV, @options)
|
|
126
|
+
query = Yobi.args.parse_query(ARGV, @options)
|
|
127
|
+
headers = Yobi.args.parse_headers(ARGV, @options)
|
|
106
128
|
|
|
107
129
|
# prepare authentication header if auth is provided
|
|
108
130
|
Yobi.args.auth_header(headers, @options) if @options[:auth]
|
|
109
131
|
|
|
110
|
-
Yobi::Http.request(method, url, data: data, headers: headers, options: @options) do |http, request|
|
|
132
|
+
Yobi::Http.request(method, url, data: data, headers: headers, query: query, options: @options) do |http, request|
|
|
111
133
|
options = @options
|
|
112
134
|
|
|
113
135
|
# follow redirects, offline, download or standard request mode
|
data/lib/yobi/cli/arguments.rb
CHANGED
|
@@ -22,12 +22,16 @@ module Yobi
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def parse_query(args, _options)
|
|
26
|
+
args.select { |arg| arg.match?(/::/) }.map.to_h { |arg| arg.split("::", 2).map(&:strip) }
|
|
27
|
+
end
|
|
28
|
+
|
|
25
29
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
26
|
-
def parse_data(args)
|
|
27
|
-
args.select { |arg| arg.match?("^.*(
|
|
30
|
+
def parse_data(args, _options)
|
|
31
|
+
args.select { |arg| arg.match?("^.*(={1}|:=|=@|:=@).*$") }.map do |arg|
|
|
28
32
|
case arg
|
|
29
33
|
when /:=@/
|
|
30
|
-
arg.split(
|
|
34
|
+
arg.split(":=@", 2).map do |part|
|
|
31
35
|
part = String(part)&.strip
|
|
32
36
|
File.exist?(part) ? JSON.parse(File.read(part)) : part
|
|
33
37
|
end
|
|
@@ -47,15 +51,18 @@ module Yobi
|
|
|
47
51
|
else
|
|
48
52
|
arg.split("=", 2).map(&:strip)
|
|
49
53
|
end
|
|
50
|
-
end
|
|
54
|
+
end.compact.to_h
|
|
51
55
|
end
|
|
52
56
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
53
57
|
|
|
54
|
-
def parse_headers(args)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
def parse_headers(args, options)
|
|
59
|
+
content_type = content_type_for options[:content_type]
|
|
60
|
+
|
|
61
|
+
{ "Content-Type" => content_type, "User-Agent" => "#{Yobi.name}/#{Yobi::VERSION}" }.merge(
|
|
62
|
+
args
|
|
63
|
+
.select { |arg| arg.match?(/:{1}/) && !arg.match?(/:=/) && !arg.match?(/::/) }
|
|
64
|
+
.map.to_h { |arg| arg.split(/:{1}/, 2).map(&:strip) }
|
|
65
|
+
)
|
|
59
66
|
end
|
|
60
67
|
|
|
61
68
|
def auth_header(headers, options)
|
|
@@ -73,6 +80,25 @@ module Yobi
|
|
|
73
80
|
exit 1
|
|
74
81
|
end
|
|
75
82
|
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def content_type_for(value)
|
|
87
|
+
case value
|
|
88
|
+
when :form
|
|
89
|
+
"application/x-www-form-urlencoded"
|
|
90
|
+
when :multipart
|
|
91
|
+
"multipart/form-data"
|
|
92
|
+
when :xml
|
|
93
|
+
"application/xml"
|
|
94
|
+
when :binary
|
|
95
|
+
"application/octet-stream"
|
|
96
|
+
when :json, nil
|
|
97
|
+
"application/json"
|
|
98
|
+
else
|
|
99
|
+
"application/json"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
76
102
|
end
|
|
77
103
|
end
|
|
78
104
|
end
|
data/lib/yobi/http.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "json"
|
|
3
4
|
require "net/http"
|
|
4
5
|
|
|
5
6
|
module Yobi
|
|
@@ -7,10 +8,22 @@ module Yobi
|
|
|
7
8
|
module Http
|
|
8
9
|
METHODS = %w[GET POST PUT DELETE PATCH HEAD OPTIONS].freeze
|
|
9
10
|
|
|
11
|
+
CONTENT_TYPES = {
|
|
12
|
+
text: "text/plain",
|
|
13
|
+
html: "text/html",
|
|
14
|
+
form: "application/x-www-form-urlencoded",
|
|
15
|
+
multipart: "multipart/form-data",
|
|
16
|
+
xml: "application/xml",
|
|
17
|
+
binary: "application/octet-stream",
|
|
18
|
+
json: "application/json"
|
|
19
|
+
}.freeze
|
|
20
|
+
|
|
10
21
|
class << self
|
|
11
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
12
|
-
def request(method, url, data: {}, headers: {}, options: {})
|
|
22
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/ParameterLists
|
|
23
|
+
def request(method, url, data: {}, query: {}, headers: {}, options: {})
|
|
13
24
|
@uri = URI(url)
|
|
25
|
+
@uri.query = URI.encode_www_form(**query) unless query.empty?
|
|
26
|
+
|
|
14
27
|
@options = options
|
|
15
28
|
@method = method.capitalize
|
|
16
29
|
|
|
@@ -33,7 +46,7 @@ module Yobi
|
|
|
33
46
|
exit 1
|
|
34
47
|
end
|
|
35
48
|
end
|
|
36
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
49
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/ParameterLists
|
|
37
50
|
|
|
38
51
|
# rubocop:disable Metrics/ParameterLists
|
|
39
52
|
def follow_redirects(response, url, method, data, headers, options)
|
|
@@ -50,7 +63,7 @@ module Yobi
|
|
|
50
63
|
end
|
|
51
64
|
# rubocop:enable Metrics/ParameterLists
|
|
52
65
|
|
|
53
|
-
# rubocop:disable Metrics/
|
|
66
|
+
# rubocop:disable Metrics/AbcSize
|
|
54
67
|
def offline_mode(_request, options)
|
|
55
68
|
Net::HTTP.class_eval do
|
|
56
69
|
def connect; end
|
|
@@ -59,7 +72,7 @@ module Yobi
|
|
|
59
72
|
options[:verbose] = true
|
|
60
73
|
|
|
61
74
|
Net::HTTPResponse.new("1.1", "200", "OK").tap do |response|
|
|
62
|
-
response["Content-Type"] =
|
|
75
|
+
response["Content-Type"] = CONTENT_TYPES.fetch(options[:content_type], CONTENT_TYPES[:json])
|
|
63
76
|
response["Access-Control-Allow-Credentials"] = true
|
|
64
77
|
response["Access-Control-Allow-Origin"] = "*"
|
|
65
78
|
response["Connection"] = "close"
|
|
@@ -71,9 +84,9 @@ module Yobi
|
|
|
71
84
|
response.instance_variable_set(:@read, true)
|
|
72
85
|
end
|
|
73
86
|
end
|
|
74
|
-
# rubocop:enable Metrics/
|
|
87
|
+
# rubocop:enable Metrics/AbcSize
|
|
75
88
|
|
|
76
|
-
# rubocop:disable Metrics/
|
|
89
|
+
# rubocop:disable Metrics/AbcSize
|
|
77
90
|
def download(request, http, options)
|
|
78
91
|
http.request(request) do |response|
|
|
79
92
|
url = request.uri.to_s
|
|
@@ -93,7 +106,7 @@ module Yobi
|
|
|
93
106
|
|
|
94
107
|
exit 0
|
|
95
108
|
end
|
|
96
|
-
# rubocop:enable Metrics/
|
|
109
|
+
# rubocop:enable Metrics/AbcSize
|
|
97
110
|
end
|
|
98
111
|
end
|
|
99
112
|
end
|
data/lib/yobi/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yobi-http
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.16.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel Vinciguerra
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-03-05 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: base64
|