sinew 2.0.2 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|