sinew 2.0.2 → 3.0.1
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/.github/workflows/test.yml +26 -0
- data/.rubocop.yml +9 -6
- data/.vscode/settings.json +0 -10
- data/Gemfile +9 -0
- data/README.md +62 -54
- data/Rakefile +33 -18
- data/bin/sinew +2 -0
- data/lib/sinew.rb +0 -1
- data/lib/sinew/connection.rb +52 -0
- data/lib/sinew/connection/log_formatter.rb +22 -0
- data/lib/sinew/connection/rate_limit.rb +29 -0
- data/lib/sinew/core_ext.rb +1 -1
- data/lib/sinew/dsl.rb +10 -6
- data/lib/sinew/main.rb +29 -56
- data/lib/sinew/output.rb +7 -16
- data/lib/sinew/request.rb +22 -87
- data/lib/sinew/response.rb +8 -57
- data/lib/sinew/runtime_options.rb +4 -4
- data/lib/sinew/version.rb +1 -1
- data/sample.sinew +2 -2
- data/sinew.gemspec +16 -18
- metadata +38 -110
- data/.travis.yml +0 -4
- data/lib/sinew/cache.rb +0 -79
- data/test/legacy/eu.httpbin.org/head/redirect,3 +0 -51
- data/test/legacy/eu.httpbin.org/head/status,500 +0 -1
- data/test/legacy/eu.httpbin.org/redirect,3 +0 -11
- data/test/legacy/eu.httpbin.org/status,500 +0 -1
- data/test/legacy/legacy.sinew +0 -2
- data/test/recipes/array_header.sinew +0 -6
- data/test/recipes/basic.sinew +0 -8
- data/test/recipes/dups.sinew +0 -7
- data/test/recipes/implicit_header.sinew +0 -5
- data/test/recipes/limit.sinew +0 -11
- data/test/recipes/noko.sinew +0 -9
- data/test/recipes/uri.sinew +0 -11
- data/test/recipes/xml.sinew +0 -8
- data/test/test.html +0 -45
- data/test/test_cache.rb +0 -69
- data/test/test_helper.rb +0 -123
- data/test/test_legacy.rb +0 -23
- data/test/test_main.rb +0 -34
- data/test/test_nokogiri_ext.rb +0 -18
- data/test/test_output.rb +0 -56
- data/test/test_recipes.rb +0 -60
- data/test/test_requests.rb +0 -135
- data/test/test_utf8.rb +0 -39
data/test/test_nokogiri_ext.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
class TestNokogiriExt < MiniTest::Test
|
4
|
-
def test_inner_text
|
5
|
-
assert_equal('hello world', noko.css('li').inner_text)
|
6
|
-
assert_equal('<li>hello</li> <li>world</li>', noko.css('ul').inner_html.squish)
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_just_me
|
10
|
-
assert_equal('a', noko.css('div').text_just_me.squish)
|
11
|
-
assert_equal('b b', noko.css('p').text_just_me.squish)
|
12
|
-
end
|
13
|
-
|
14
|
-
def noko
|
15
|
-
@noko ||= Nokogiri::HTML(HTML).css('#nokogiri_ext')
|
16
|
-
end
|
17
|
-
protected :noko
|
18
|
-
end
|
data/test/test_output.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
class TestOutput < MiniTest::Test
|
4
|
-
def test_filenames
|
5
|
-
sinew = Sinew::Main.new(recipe: 'gub.sinew')
|
6
|
-
assert_equal 'gub.csv', sinew.output.filename
|
7
|
-
sinew = Sinew::Main.new(recipe: 'gub')
|
8
|
-
assert_equal 'gub.csv', sinew.output.filename
|
9
|
-
sinew = Sinew::Main.new(recipe: '/somewhere/gub.sinew')
|
10
|
-
assert_equal '/somewhere/gub.csv', sinew.output.filename
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_normalization
|
14
|
-
output = Sinew::Output.new(nil)
|
15
|
-
|
16
|
-
#
|
17
|
-
# simple types
|
18
|
-
#
|
19
|
-
|
20
|
-
assert_equal '', output.send(:normalize, nil)
|
21
|
-
assert_equal '', output.send(:normalize, '')
|
22
|
-
assert_equal 'text', output.send(:normalize, 'text')
|
23
|
-
assert_equal '123', output.send(:normalize, 123)
|
24
|
-
assert_equal('1|2', output.send(:normalize, [ 1, 2 ]))
|
25
|
-
|
26
|
-
#
|
27
|
-
# nokogiri
|
28
|
-
#
|
29
|
-
|
30
|
-
noko = Nokogiri::HTML(HTML)
|
31
|
-
|
32
|
-
# node => text
|
33
|
-
assert_equal('text', output.send(:normalize, noko.css('#element')))
|
34
|
-
# nodes => text joined with space
|
35
|
-
assert_equal('text1 text2', output.send(:normalize, noko.css('.e')))
|
36
|
-
|
37
|
-
#
|
38
|
-
# string cleanups
|
39
|
-
#
|
40
|
-
|
41
|
-
# strip_html_tags
|
42
|
-
assert_equal('gub', output.send(:normalize, '<tag>gub</tag>'))
|
43
|
-
# strip_html_tags and replace with spaces
|
44
|
-
assert_equal('hello world', output.send(:normalize, '<tag>hello<br>world</tag>'))
|
45
|
-
# convert_smart_punctuation
|
46
|
-
assert_equal('"gub"', output.send(:normalize, "\302\223gub\302\224"))
|
47
|
-
# convert_accented_html_entities
|
48
|
-
assert_equal('a', output.send(:normalize, 'á'))
|
49
|
-
# convert_miscellaneous_html_entities
|
50
|
-
assert_equal('<>', output.send(:normalize, '<>'))
|
51
|
-
# to_ascii
|
52
|
-
assert_equal('cafe', output.send(:normalize, "caf\xc3\xa9"))
|
53
|
-
# squish
|
54
|
-
assert_equal('hello world', output.send(:normalize, "\nhello \t \rworld"))
|
55
|
-
end
|
56
|
-
end
|
data/test/test_recipes.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
class TestRecipe < MiniTest::Test
|
4
|
-
DIR = File.expand_path('recipes', __dir__)
|
5
|
-
TEST_SINEW = "#{TMP}/test.sinew".freeze
|
6
|
-
TEST_CSV = "#{TMP}/test.csv".freeze
|
7
|
-
|
8
|
-
def test_recipes
|
9
|
-
Dir.chdir(DIR) do
|
10
|
-
Dir['*.sinew'].sort.each do |filename|
|
11
|
-
recipe = IO.read(filename)
|
12
|
-
|
13
|
-
# get ready
|
14
|
-
IO.write(TEST_SINEW, recipe)
|
15
|
-
sinew = Sinew::Main.new(cache: TMP, quiet: true, recipe: TEST_SINEW)
|
16
|
-
|
17
|
-
# read OPTIONS
|
18
|
-
if options = options_from(recipe)
|
19
|
-
options.each do |key, value|
|
20
|
-
sinew.options[key] = value
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# read OUTPUT
|
25
|
-
output = output_from(recipe, filename)
|
26
|
-
|
27
|
-
# run
|
28
|
-
sinew.run
|
29
|
-
|
30
|
-
# assert
|
31
|
-
csv = IO.read(TEST_CSV)
|
32
|
-
assert_equal(output, csv, "Output didn't match for recipes/#{filename}")
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def options_from(recipe)
|
38
|
-
if options = recipe[/^#\s*OPTIONS\s*(\{.*\})/, 1]
|
39
|
-
# rubocop:disable Security/Eval
|
40
|
-
eval(options)
|
41
|
-
# rubocop:enable Security/Eval
|
42
|
-
end
|
43
|
-
end
|
44
|
-
protected :options_from
|
45
|
-
|
46
|
-
def output_from(recipe, filename)
|
47
|
-
lines = recipe.split("\n")
|
48
|
-
first_line = lines.index { |i| i =~ /^# OUTPUT/ }
|
49
|
-
if !first_line
|
50
|
-
raise "# OUTPUT not found in recipes/#{filename}"
|
51
|
-
end
|
52
|
-
|
53
|
-
output = lines[first_line + 1..-1]
|
54
|
-
output = output.map { |i| i.gsub(/^# /, '') }
|
55
|
-
output = output.join("\n")
|
56
|
-
output += "\n"
|
57
|
-
output
|
58
|
-
end
|
59
|
-
protected :output_from
|
60
|
-
end
|
data/test/test_requests.rb
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
class TestRequests < MiniTest::Test
|
4
|
-
def test_user_agent
|
5
|
-
sinew.dsl.get('http://httpbin.org/get', a: 1, b: 2)
|
6
|
-
assert_match(/sinew/, sinew.dsl.json[:headers][:'User-Agent'])
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_basic_methods
|
10
|
-
sinew.dsl.get('http://httpbin.org/get', a: 1, b: 2)
|
11
|
-
assert_equal({ a: '1', b: '2' }, sinew.dsl.json[:args])
|
12
|
-
|
13
|
-
sinew.dsl.post('http://httpbin.org/post', a: 1, b: 2)
|
14
|
-
assert_equal({ a: '1', b: '2' }, sinew.dsl.json[:form])
|
15
|
-
|
16
|
-
sinew.dsl.post_json('http://httpbin.org/post', a: 1, b: 2)
|
17
|
-
assert_equal({ a: 1, b: 2 }, sinew.dsl.json[:json])
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_custom_headers
|
21
|
-
sinew.dsl.http('get', 'http://httpbin.org/get', headers: { "User-Agent": '007' })
|
22
|
-
assert_match(/007/, sinew.dsl.json[:headers][:'User-Agent'])
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_redirects
|
26
|
-
# absolute redirect
|
27
|
-
sinew.dsl.get('http://httpbin.org/redirect/2')
|
28
|
-
assert_equal 'http://httpbin.org/get', sinew.dsl.url
|
29
|
-
|
30
|
-
# and relative redirect
|
31
|
-
sinew.dsl.get('http://httpbin.org/relative-redirect/2')
|
32
|
-
assert_equal 'http://httpbin.org/get', sinew.dsl.url
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_errors
|
36
|
-
skip if test_network?
|
37
|
-
|
38
|
-
# 500
|
39
|
-
assert_output(/failed with 500/) do
|
40
|
-
sinew.dsl.get('http://httpbin.org/status/500')
|
41
|
-
assert_equal '500', sinew.dsl.raw
|
42
|
-
end
|
43
|
-
|
44
|
-
# timeout
|
45
|
-
assert_output(/failed with 999/) do
|
46
|
-
sinew.dsl.get('http://httpbin.org/delay/1')
|
47
|
-
assert_equal 'timeout', sinew.dsl.raw
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def test_retry_timeout
|
52
|
-
skip if test_network?
|
53
|
-
|
54
|
-
errors = 2
|
55
|
-
stub_request(:get, %r{http://[^/]+/error}).to_return do
|
56
|
-
if errors > 0
|
57
|
-
errors -= 1
|
58
|
-
raise Timeout::Error
|
59
|
-
end
|
60
|
-
{ body: 'done', status: 200 }
|
61
|
-
end
|
62
|
-
sinew.dsl.get('http://httpbin.org/error')
|
63
|
-
assert_equal 0, errors
|
64
|
-
assert_equal 'done', sinew.dsl.raw
|
65
|
-
end
|
66
|
-
|
67
|
-
def test_retry_500
|
68
|
-
skip if test_network?
|
69
|
-
|
70
|
-
errors = 2
|
71
|
-
stub_request(:get, %r{http://[^/]+/error}).to_return do
|
72
|
-
if errors > 0
|
73
|
-
errors -= 1
|
74
|
-
return { status: 500 }
|
75
|
-
end
|
76
|
-
{ body: 'done', status: 200 }
|
77
|
-
end
|
78
|
-
sinew.dsl.get('http://httpbin.org/error')
|
79
|
-
assert_equal 0, errors
|
80
|
-
assert_equal 'done', sinew.dsl.raw
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_cache_key
|
84
|
-
# empty
|
85
|
-
req = Sinew::Request.new(sinew, 'get', 'http://host')
|
86
|
-
assert_equal req.cache_key, 'host/_root_'
|
87
|
-
|
88
|
-
# path
|
89
|
-
req = Sinew::Request.new(sinew, 'get', 'http://host/path')
|
90
|
-
assert_equal req.cache_key, 'host/path'
|
91
|
-
|
92
|
-
# query
|
93
|
-
req = Sinew::Request.new(sinew, 'get', 'http://host/path', query: { a: 'b' })
|
94
|
-
assert_equal req.cache_key, 'host/path,a=b'
|
95
|
-
|
96
|
-
# post with body
|
97
|
-
req = Sinew::Request.new(sinew, 'post', 'http://host/path', body: { c: 'd' })
|
98
|
-
assert_equal req.cache_key, 'host/post,path,c=d'
|
99
|
-
|
100
|
-
# too long should turn into digest
|
101
|
-
path = 'xyz' * 123
|
102
|
-
req = Sinew::Request.new(sinew, 'get', "http://host/#{path}")
|
103
|
-
assert_equal "host/#{Digest::MD5.hexdigest(path)}", req.cache_key
|
104
|
-
end
|
105
|
-
|
106
|
-
def test_before_generate_cache_key
|
107
|
-
sinew.runtime_options.before_generate_cache_key = method(:redact_cache_key)
|
108
|
-
req = Sinew::Request.new(sinew, 'get', 'http://host', query: { secret: 'xyz' })
|
109
|
-
assert_equal 'host/secret=redacted', req.cache_key
|
110
|
-
end
|
111
|
-
|
112
|
-
def test_urls
|
113
|
-
# simple
|
114
|
-
req = Sinew::Request.new(sinew, 'get', 'https://host')
|
115
|
-
assert_equal 'https://host', req.uri.to_s
|
116
|
-
|
117
|
-
# with query
|
118
|
-
req = Sinew::Request.new(sinew, 'get', 'https://host', query: { a: 1 })
|
119
|
-
assert_equal 'https://host?a=1', req.uri.to_s
|
120
|
-
|
121
|
-
# entity decoding
|
122
|
-
req = Sinew::Request.new(sinew, 'get', 'https://host?a=<5')
|
123
|
-
assert_equal 'https://host?a=%3C5', req.uri.to_s
|
124
|
-
|
125
|
-
# sloppy urls
|
126
|
-
req = Sinew::Request.new(sinew, 'get', 'https://host?a=b c&d=f\'g')
|
127
|
-
assert_equal 'https://host?a=b%20c&d=f%27g', req.uri.to_s
|
128
|
-
end
|
129
|
-
|
130
|
-
def redact_cache_key(key)
|
131
|
-
key[:query].gsub!(/secret=[^&]+/, 'secret=redacted')
|
132
|
-
key
|
133
|
-
end
|
134
|
-
protected :redact_cache_key
|
135
|
-
end
|
data/test/test_utf8.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
|
-
class TestRequests < MiniTest::Test
|
4
|
-
def test_get
|
5
|
-
# network (or stub)
|
6
|
-
sinew.dsl.get('http://httpbin.org/get')
|
7
|
-
assert_equal 'UTF-8', sinew.dsl.raw.encoding.name
|
8
|
-
|
9
|
-
# disk
|
10
|
-
sinew.dsl.get('http://httpbin.org/get')
|
11
|
-
assert_equal 'UTF-8', sinew.dsl.raw.encoding.name
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_utf8
|
15
|
-
skip if !test_network?
|
16
|
-
|
17
|
-
# network
|
18
|
-
sinew.dsl.get('http://httpbin.org/encoding/utf8')
|
19
|
-
assert_equal 'UTF-8', sinew.dsl.raw.encoding.name
|
20
|
-
assert_match(/∑/, sinew.dsl.raw)
|
21
|
-
|
22
|
-
# disk
|
23
|
-
sinew.dsl.get('http://httpbin.org/encoding/utf8')
|
24
|
-
assert_equal 'UTF-8', sinew.dsl.raw.encoding.name
|
25
|
-
assert_match(/∑/, sinew.dsl.raw)
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_encode
|
29
|
-
skip if !test_network?
|
30
|
-
|
31
|
-
# network
|
32
|
-
sinew.dsl.get('https://www.google.co.jp')
|
33
|
-
assert_equal 'UTF-8', sinew.dsl.raw.encoding.name
|
34
|
-
|
35
|
-
# disk
|
36
|
-
sinew.dsl.get('https://www.google.co.jp')
|
37
|
-
assert_equal 'UTF-8', sinew.dsl.raw.encoding.name
|
38
|
-
end
|
39
|
-
end
|