saper 0.5.2 → 0.5.3
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 +4 -3
- data/Rakefile +7 -5
- data/bin/saper +51 -1
- data/lib/saper/actions/create_atom.rb +0 -5
- data/lib/saper/actions/nothing.rb +2 -0
- data/lib/saper/actions/remove_matching.rb +1 -1
- data/lib/saper/actions/run_recipe.rb +5 -5
- data/lib/saper/actions/run_recipe_and_save.rb +5 -5
- data/lib/saper/actions/select_matching.rb +1 -1
- data/lib/saper/actions/set_input.rb +0 -5
- data/lib/saper/core/action.rb +69 -53
- data/lib/saper/core/argument.rb +3 -0
- data/lib/saper/core/browser.rb +3 -2
- data/lib/saper/core/error.rb +4 -1
- data/lib/saper/core/keychain.rb +2 -2
- data/lib/saper/core/logger.rb +9 -54
- data/lib/saper/core/recipe.rb +36 -5
- data/lib/saper/core/result.rb +36 -5
- data/lib/saper/core/runtime.rb +17 -11
- data/lib/saper/core/stack.rb +17 -1
- data/lib/saper/items/html.rb +1 -1
- data/lib/saper/items/nothing.rb +9 -0
- data/lib/saper/items/xml.rb +5 -1
- data/lib/saper/version.rb +1 -1
- data/lib/tungsten/lib/README +5 -0
- data/lib/tungsten/lib/test.rb +18 -0
- data/lib/tungsten/lib/tungsten.rb +33 -0
- data/lib/tungsten/lib/tungsten/headers.rb +37 -0
- data/lib/tungsten/lib/tungsten/jar.rb +17 -0
- data/lib/tungsten/lib/tungsten/request.rb +102 -0
- data/lib/tungsten/lib/tungsten/response.rb +101 -0
- data/spec/actions/append_with_spec.rb +144 -21
- data/spec/actions/convert_to_html_spec.rb +126 -11
- data/spec/actions/convert_to_json_spec.rb +126 -11
- data/spec/actions/convert_to_markdown_spec.rb +126 -11
- data/spec/actions/convert_to_time_spec.rb +150 -15
- data/spec/actions/convert_to_xml_spec.rb +136 -11
- data/spec/actions/create_atom_spec.rb +116 -7
- data/spec/actions/fetch_spec.rb +110 -3
- data/spec/actions/find_first_spec.rb +149 -24
- data/spec/actions/find_spec.rb +167 -19
- data/spec/actions/get_attribute_spec.rb +145 -15
- data/spec/actions/get_contents_spec.rb +125 -4
- data/spec/actions/get_text_spec.rb +125 -4
- data/spec/actions/nothing_spec.rb +119 -4
- data/spec/actions/prepend_with_spec.rb +148 -22
- data/spec/actions/remove_after_spec.rb +160 -4
- data/spec/actions/remove_before_spec.rb +160 -4
- data/spec/actions/remove_matching_spec.rb +164 -4
- data/spec/actions/remove_tags_spec.rb +1 -1
- data/spec/actions/replace_spec.rb +1 -1
- data/spec/actions/run_recipe_and_save_spec.rb +1 -1
- data/spec/actions/run_recipe_spec.rb +1 -1
- data/spec/actions/save_spec.rb +1 -1
- data/spec/actions/select_matching_spec.rb +164 -4
- data/spec/actions/set_input_spec.rb +1 -1
- data/spec/actions/skip_tags_spec.rb +1 -1
- data/spec/actions/split_spec.rb +1 -1
- data/spec/arguments/attribute_spec.rb +1 -1
- data/spec/arguments/recipe_spec.rb +1 -1
- data/spec/arguments/text_spec.rb +1 -1
- data/spec/arguments/timezone_spec.rb +1 -1
- data/spec/arguments/variable_spec.rb +1 -1
- data/spec/arguments/xpath_spec.rb +1 -1
- data/spec/core/action_spec.rb +25 -13
- data/spec/core/argument_spec.rb +55 -31
- data/spec/core/browser_spec.rb +21 -11
- data/spec/core/dsl_spec.rb +1 -1
- data/spec/core/item_spec.rb +1 -1
- data/spec/core/keychain_spec.rb +1 -1
- data/spec/core/logger_spec.rb +1 -1
- data/spec/core/namespace_spec.rb +1 -1
- data/spec/core/recipe_spec.rb +85 -51
- data/spec/core/result_spec.rb +1 -1
- data/spec/core/runtime_spec.rb +45 -27
- data/spec/core/stack_spec.rb +1 -1
- data/spec/core/type_spec.rb +1 -1
- data/spec/integration/simple_invalid_spec.rb +46 -9
- data/spec/integration/simple_valid_spec.rb +9 -9
- data/spec/items/atom_spec.rb +7 -7
- data/spec/items/document_spec.rb +29 -29
- data/spec/items/html_spec.rb +80 -48
- data/spec/items/json_spec.rb +17 -11
- data/spec/items/markdown_spec.rb +30 -18
- data/spec/items/nothing_spec.rb +1 -1
- data/spec/items/text_spec.rb +12 -10
- data/spec/items/time_spec.rb +35 -21
- data/spec/items/url_spec.rb +1 -1
- data/spec/items/xml_spec.rb +75 -42
- data/spec/spec_helper.rb +90 -2
- metadata +51 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fd213bbb0ccdf59a2743bea247a3466463d71e14
|
|
4
|
+
data.tar.gz: 682c8ef1d14f62253819905414c964837f8818d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b31225725e71ed95b1fe7af32a912755ac5d0198acd8e5a0e968c31c4ef97dc517ed0ce786ec6e9992975809c7493632d42a1de03dcd37d413e6318a9598d6d0
|
|
7
|
+
data.tar.gz: 9c656ccb71b79b7b708db2b7f9116af6c3675a9df3cf2a7fdc1dda7b26fda64c5572481ac8474434e2b0f2c483786f3c38ea6ac195f98c63ee240786c33a3de8
|
data/README.md
CHANGED
|
@@ -11,6 +11,7 @@ Common use scenarios:
|
|
|
11
11
|
|
|
12
12
|
[](http://badge.fury.io/rb/saper)
|
|
13
13
|
[](https://travis-ci.org/merimond/saper)
|
|
14
|
+
[](https://codeclimate.com/github/merimond/saper)
|
|
14
15
|
|
|
15
16
|
## Installing
|
|
16
17
|
|
|
@@ -43,7 +44,7 @@ Given that file is saved as _myrecipe.txt_, you can now use the command line:
|
|
|
43
44
|
Alternatively, you can use Ruby:
|
|
44
45
|
|
|
45
46
|
#!/usr/bin/env ruby
|
|
46
|
-
Saper.
|
|
47
|
+
Saper.run_from_file("myrecipe.txt", :bloomberg).serialize
|
|
47
48
|
|
|
48
49
|
## Data flow
|
|
49
50
|
|
|
@@ -109,7 +110,7 @@ Below is a list of all available actions:
|
|
|
109
110
|
|
|
110
111
|
- **set_input** (string) - sets input for the following action.
|
|
111
112
|
- **create_atom** - create an Atom from saved variables.
|
|
112
|
-
- **run_recipe_and_save** (
|
|
113
|
+
- **run_recipe_and_save** (recipe, variable) - run another recipe and save its result as a variable.
|
|
113
114
|
- **run_recipe** (recipe) - run another recipe and use it's output as input for the next action.
|
|
114
115
|
- **save** (variable) - save input as a variable.
|
|
115
116
|
|
|
@@ -126,4 +127,4 @@ Below is a list of all available actions:
|
|
|
126
127
|
|
|
127
128
|
Copyright (c) 2013 Merimond Corporation. MIT license, see [LICENSE] for details.
|
|
128
129
|
|
|
129
|
-
[LICENSE]: http://github.com/merimond/saper/blob/master/LICENSE
|
|
130
|
+
[LICENSE]: http://github.com/merimond/saper/blob/master/LICENSE
|
data/Rakefile
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
require 'bundler'
|
|
3
|
-
require 'rake/testtask'
|
|
3
|
+
#require 'rake/testtask'
|
|
4
4
|
require 'yard'
|
|
5
5
|
|
|
6
6
|
Bundler.require
|
|
7
7
|
Bundler::GemHelper.install_tasks
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
begin
|
|
10
|
+
require 'rspec/core/rake_task'
|
|
11
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
12
|
+
rescue LoadError
|
|
13
|
+
# no rspec available
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
desc "Generate docs"
|
|
@@ -16,4 +18,4 @@ YARD::Rake::YardocTask.new do |t|
|
|
|
16
18
|
t.files = ['lib/saper/**/*.rb']
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
task :default => :
|
|
21
|
+
task :default => :spec
|
data/bin/saper
CHANGED
|
@@ -14,6 +14,7 @@ Options are ...
|
|
|
14
14
|
opt :input, "Recipe input", :type => :string
|
|
15
15
|
opt :agent, "User-Agent", :type => :string
|
|
16
16
|
opt :keychain, "Keychain file", :type => :string
|
|
17
|
+
opt :verbose, "Verbose output"
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
if opts[:recipe].nil?
|
|
@@ -24,8 +25,57 @@ unless ARGV.size == 1
|
|
|
24
25
|
Trollop::die "Please specify filename"
|
|
25
26
|
end
|
|
26
27
|
|
|
28
|
+
def bold(string)
|
|
29
|
+
puts "\n\033[1m%s\033[0m" % string
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def red(string)
|
|
33
|
+
puts "\033[31m%s\033[0m" % string
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def green(string)
|
|
37
|
+
puts "\033[32m%s\033[0m" % string
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def print_value(value)
|
|
41
|
+
puts "> %s" % value.class
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def print_action_name(action, error = false)
|
|
45
|
+
error ? red(action.name) : green(action.name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def print_each_action(stack, actions)
|
|
49
|
+
actions.each_with_index do |action, i|
|
|
50
|
+
print_value stack.to_a[i]
|
|
51
|
+
print_action_name action, stack.to_a[i+1].is_a?(Saper::Error)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def print_each_stack(result, actions)
|
|
56
|
+
result.stacks.each_with_index do |stack, i|
|
|
57
|
+
bold "STACK %s / %s" % [i + 1, result.size]
|
|
58
|
+
print_each_action(stack, actions)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
if opts[:verbose]
|
|
63
|
+
bold "ACTION LOG"
|
|
64
|
+
opts[:logger] = Saper::Logger.new($stdout)
|
|
65
|
+
end
|
|
66
|
+
|
|
27
67
|
begin
|
|
28
|
-
|
|
68
|
+
recipe = Saper.load(ARGV.first)[opts[:recipe]]
|
|
69
|
+
result = recipe.run(opts[:input], opts)
|
|
70
|
+
if opts[:verbose]
|
|
71
|
+
bold "RESULTS: %s" % result.size
|
|
72
|
+
end
|
|
73
|
+
result.to_serialized_array.each do |result|
|
|
74
|
+
result.nil? ? red("null") : green(result)
|
|
75
|
+
end
|
|
76
|
+
if opts[:verbose] && result.failure?
|
|
77
|
+
print_each_stack(result, recipe.actions)
|
|
78
|
+
end
|
|
29
79
|
rescue Errno::ENOENT => e
|
|
30
80
|
Trollop::die("File not found: %s" % ARGV.first)
|
|
31
81
|
rescue NoMethodError => e
|
|
@@ -3,20 +3,20 @@ module Saper
|
|
|
3
3
|
class RunRecipe < Action
|
|
4
4
|
|
|
5
5
|
argument :recipe
|
|
6
|
-
accepts :anything, :returns => Proc.new { |instance|
|
|
6
|
+
accepts :anything, :returns => Proc.new { |instance| instance.args.first.requires }
|
|
7
7
|
|
|
8
8
|
run do |runtime, input, subrecipe|
|
|
9
9
|
subrecipe.run(input).to_saper
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
# Overrides default logic
|
|
13
|
-
def
|
|
14
|
-
args.first.
|
|
13
|
+
def accepts?(type)
|
|
14
|
+
args.first.accepts?(type)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# Overrides default logic
|
|
18
|
-
def
|
|
19
|
-
args.first.
|
|
18
|
+
def multiple?
|
|
19
|
+
args.first.multiple?
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
end
|
|
@@ -2,19 +2,19 @@ module Saper
|
|
|
2
2
|
module Actions
|
|
3
3
|
class RunRecipeAndSave < Action
|
|
4
4
|
|
|
5
|
-
argument :variable
|
|
6
5
|
argument :recipe
|
|
7
|
-
|
|
6
|
+
argument :variable
|
|
7
|
+
accepts :anything, :returns => Proc.new { |instance| instance.args.first.requires }
|
|
8
8
|
|
|
9
|
-
run do |runtime, input,
|
|
9
|
+
run do |runtime, input, subrecipe, variable|
|
|
10
10
|
result = subrecipe.run(input).to_saper
|
|
11
11
|
runtime[variable] = result unless result.nil?
|
|
12
12
|
input
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
# Overrides default logic
|
|
16
|
-
def
|
|
17
|
-
args.
|
|
16
|
+
def accepts?(type)
|
|
17
|
+
args.first.accepts?(type)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
end
|
data/lib/saper/core/action.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Saper
|
|
2
2
|
class Action
|
|
3
3
|
|
|
4
|
+
INPUT_TYPES = %i(text atom document html json markdown nothing time url xml)
|
|
5
|
+
|
|
4
6
|
# Tracks subclasses of Saper::Action.
|
|
5
7
|
# @return [Class]
|
|
6
8
|
def self.inherited(base)
|
|
@@ -52,47 +54,17 @@ module Saper
|
|
|
52
54
|
return @types.nil? ? [] : @types.keys
|
|
53
55
|
end
|
|
54
56
|
if input == :anything
|
|
55
|
-
|
|
57
|
+
INPUT_TYPES.each { |type| accepts(type, options) }
|
|
56
58
|
end
|
|
57
59
|
output = options[:returns] || input
|
|
58
|
-
unless Item.exists?(input)
|
|
59
|
-
raise(InvalidInput, "Invalid input type: %s" % input)
|
|
60
|
-
end
|
|
61
|
-
if output.is_a?(Symbol) && !Item.exists?(output)
|
|
62
|
-
raise(InvalidInput, "Invalid output type: %s" % output)
|
|
63
|
-
end
|
|
64
60
|
@types ||= {}
|
|
65
61
|
@types[input] = output
|
|
66
62
|
end
|
|
67
63
|
|
|
68
|
-
# Returns `true` if action accepts no input.
|
|
69
|
-
# @return [Boolean]
|
|
70
|
-
def self.accepts_nothing?
|
|
71
|
-
@types.nil?
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Returns `true` if action accepts at least some kind of input.
|
|
75
|
-
# @return [Boolean]
|
|
76
|
-
def self.accepts_something?
|
|
77
|
-
!accepts_nothing? && !accepts_anything?
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Returns `true` if action accepts any kind of input.
|
|
81
|
-
# @return [Boolean]
|
|
82
|
-
def self.accepts_anything?
|
|
83
|
-
@types.empty?
|
|
84
|
-
end
|
|
85
|
-
|
|
86
64
|
# Returns `true` if action accepts specified type as input.
|
|
87
65
|
# @param type [Symbol]
|
|
88
66
|
# @return [Boolean]
|
|
89
67
|
def self.accepts?(type)
|
|
90
|
-
if accepts_nothing?
|
|
91
|
-
return false
|
|
92
|
-
end
|
|
93
|
-
if accepts_anything?
|
|
94
|
-
return true
|
|
95
|
-
end
|
|
96
68
|
accepts.include?(type)
|
|
97
69
|
end
|
|
98
70
|
|
|
@@ -102,6 +74,13 @@ module Saper
|
|
|
102
74
|
@block ||= block
|
|
103
75
|
end
|
|
104
76
|
|
|
77
|
+
# Returns the type of output for specfied input type.
|
|
78
|
+
# @param type [Symbol] argument type (e.g. :text, :xpath)
|
|
79
|
+
# @return [Array<Symbol>]
|
|
80
|
+
def self.output_for(type)
|
|
81
|
+
accepts?(type) ? @types[type] : :nothing
|
|
82
|
+
end
|
|
83
|
+
|
|
105
84
|
# Returns `true` if action returns multiple items. Note that this method will report incorrect data for some actions. Use #multiple? instead.
|
|
106
85
|
def self.returns_multiple_items?
|
|
107
86
|
@multiple == true
|
|
@@ -168,25 +147,9 @@ module Saper
|
|
|
168
147
|
# @return [void] depends on action type
|
|
169
148
|
def run(input = nil, runtime = nil)
|
|
170
149
|
runtime ||= Runtime.new
|
|
171
|
-
input
|
|
172
|
-
block.call(runtime, input, *args)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
# @todo
|
|
176
|
-
def validate_input(input)
|
|
177
|
-
unless self.class.accepts_something?
|
|
178
|
-
return input
|
|
179
|
-
end
|
|
180
|
-
unless input.is_a?(Item)
|
|
181
|
-
input = self.class.accepts.map { |type| Item.try(type, input) }.compact.first
|
|
182
|
-
end
|
|
183
|
-
if input.nil?
|
|
184
|
-
raise(InvalidInput, input)
|
|
185
|
-
end
|
|
186
|
-
unless self.class.accepts?(input.type)
|
|
187
|
-
raise(InvalidInput, input)
|
|
188
|
-
end
|
|
189
|
-
input
|
|
150
|
+
input = validate_input(input)
|
|
151
|
+
output = block.call(runtime, input, *args)
|
|
152
|
+
validate_output output, output_for(input.type)
|
|
190
153
|
end
|
|
191
154
|
|
|
192
155
|
# Returns human readable action name.
|
|
@@ -201,10 +164,18 @@ module Saper
|
|
|
201
164
|
@options[:namespace].is_a?(Namespace) ? @options[:namespace] : nil
|
|
202
165
|
end
|
|
203
166
|
|
|
204
|
-
# Returns
|
|
167
|
+
# Returns `true` if action accepts specified type as input.
|
|
168
|
+
# @param type [Symbol]
|
|
169
|
+
# @return [Boolean]
|
|
170
|
+
def accepts?(type)
|
|
171
|
+
self.class.accepts.include?(type)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Returns the type of output for specfied input type.
|
|
175
|
+
# @param type [Symbol] argument type (e.g. :text, :xpath)
|
|
205
176
|
# @return [Array<Symbol>]
|
|
206
|
-
def
|
|
207
|
-
self.class.
|
|
177
|
+
def output_for(type)
|
|
178
|
+
out = self.class.output_for(type); out.is_a?(Proc) ? out.call(self) : out
|
|
208
179
|
end
|
|
209
180
|
|
|
210
181
|
# Returns values of action arguments.
|
|
@@ -219,6 +190,12 @@ module Saper
|
|
|
219
190
|
{ :type => self.class.type, :args => @arguments.map(&:serialize) }
|
|
220
191
|
end
|
|
221
192
|
|
|
193
|
+
# Returns a JSON representation of this action.
|
|
194
|
+
# @return [String]
|
|
195
|
+
def to_json(*args)
|
|
196
|
+
serialize.to_json(*args)
|
|
197
|
+
end
|
|
198
|
+
|
|
222
199
|
# Returns `true` if action returns multiple items.
|
|
223
200
|
# @return [Boolean]
|
|
224
201
|
def multiple?
|
|
@@ -237,5 +214,44 @@ module Saper
|
|
|
237
214
|
"\t%s %s" % [self.class.type, @arguments.map(&:to_string).join(", ")]
|
|
238
215
|
end
|
|
239
216
|
|
|
217
|
+
private
|
|
218
|
+
|
|
219
|
+
# @todo
|
|
220
|
+
def validate_output(output, type)
|
|
221
|
+
if output.is_a?(Array) && output.empty?
|
|
222
|
+
raise InvalidOutput
|
|
223
|
+
end
|
|
224
|
+
if output.is_a?(Array)
|
|
225
|
+
return output.map { |o| validate_output(o, type) }
|
|
226
|
+
end
|
|
227
|
+
if output.is_a?(Items::Nothing) && output.filtered?
|
|
228
|
+
return output
|
|
229
|
+
end
|
|
230
|
+
unless output.is_a?(Item)
|
|
231
|
+
output = Item.try(type, output)
|
|
232
|
+
end
|
|
233
|
+
if output.is_a?(Item) && output.type == type
|
|
234
|
+
return output
|
|
235
|
+
end
|
|
236
|
+
raise InvalidOutput
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# @todo
|
|
240
|
+
def validate_input(input)
|
|
241
|
+
unless input.is_a?(Item)
|
|
242
|
+
input = self.class.accepts.map { |type| Item.try(type, input) }.compact.first
|
|
243
|
+
end
|
|
244
|
+
if input.nil? && accepts?(:nothing)
|
|
245
|
+
return Items::Nothing.new
|
|
246
|
+
end
|
|
247
|
+
if input.nil?
|
|
248
|
+
raise(InvalidInput, input)
|
|
249
|
+
end
|
|
250
|
+
unless accepts?(input.type)
|
|
251
|
+
raise(InvalidInput, input)
|
|
252
|
+
end
|
|
253
|
+
input
|
|
254
|
+
end
|
|
255
|
+
|
|
240
256
|
end
|
|
241
257
|
end
|
data/lib/saper/core/argument.rb
CHANGED
data/lib/saper/core/browser.rb
CHANGED
|
@@ -52,6 +52,7 @@ module Saper
|
|
|
52
52
|
@received += resp.to_hash.to_s.size
|
|
53
53
|
@received += body.size
|
|
54
54
|
end
|
|
55
|
+
@logger.new_browser(self)
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
# Returns the number of HTTP requests.
|
|
@@ -71,7 +72,7 @@ module Saper
|
|
|
71
72
|
# @param query [Hash] query options
|
|
72
73
|
# @return [Saper::Document]
|
|
73
74
|
def get(url, query = {})
|
|
74
|
-
@logger.
|
|
75
|
+
@logger.new_get_request(url)
|
|
75
76
|
@history.push url
|
|
76
77
|
data = @mech.get(url, query)
|
|
77
78
|
Saper::Items::Document.new data.body, data.uri, data.header
|
|
@@ -84,7 +85,7 @@ module Saper
|
|
|
84
85
|
# @param query [Hash] payload
|
|
85
86
|
# @return [Saper::Document]
|
|
86
87
|
def post(url, query = {}, headers = {})
|
|
87
|
-
@logger.
|
|
88
|
+
@logger.new_post_request(url)
|
|
88
89
|
@history.push url
|
|
89
90
|
data = @mech.post(url, query, headers)
|
|
90
91
|
Saper::Items::Document.new data.body, data.uri, data.header
|