super-test 1.0.9
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 +7 -0
- data/CHANGE.txt +9 -0
- data/README.txt +13 -0
- data/bin/idb +19 -0
- data/bin/ii +113 -0
- data/bin/istart_mock +36 -0
- data/bin/istop_mock +16 -0
- data/bin/kk +181 -0
- data/bin/rubyatp +42 -0
- data/bin/start_mock +36 -0
- data/bin/stop_mock +16 -0
- data/bin/xgo +45 -0
- data/conf/conf.rb +11 -0
- data/conf/db03.yml +31 -0
- data/conf/db13.yml +37 -0
- data/conf/db19.yml +33 -0
- data/conf/online.yml +32 -0
- data/conf/super_test.yml +40 -0
- data/conf/system.yml +26 -0
- data/conf/sz00.yml +31 -0
- data/conf/sz06.yml +34 -0
- data/conf/wise00.yml +11 -0
- data/data/case.house +0 -0
- data/data/char.house +0 -0
- data/data/images/Bluehills.jpg +0 -0
- data/data/images/Sunset.jpg +0 -0
- data/data/images/Waterlilies.jpg +0 -0
- data/data/images/Winter.jpg +0 -0
- data/data/query.house +18595 -0
- data/data/user.house +8 -0
- data/lib/action/module/check_action.rb +58 -0
- data/lib/action/module/cnnt_action.rb +161 -0
- data/lib/action/module/datacenter_action.rb +48 -0
- data/lib/action/module/http_pack_helper.rb +163 -0
- data/lib/action/module/httpserver_action.rb +297 -0
- data/lib/action/module/inc.rb +21 -0
- data/lib/action/module/mcpack_action.rb +57 -0
- data/lib/action/module/sql_action.rb +84 -0
- data/lib/action/module/ssh_action.rb +37 -0
- data/lib/action/system/user_action.rb +180 -0
- data/lib/common/appium_helper.rb +217 -0
- data/lib/common/atp_helper.rb +74 -0
- data/lib/common/atp_report.rb +344 -0
- data/lib/common/data_house.rb +405 -0
- data/lib/common/data_model.rb +87 -0
- data/lib/common/http/assert_helper.rb +343 -0
- data/lib/common/http/fix_hpricot.rb +118 -0
- data/lib/common/http/html_helper.rb +362 -0
- data/lib/common/http/http_helper.rb +469 -0
- data/lib/common/http/multipart.rb +81 -0
- data/lib/common/isandbox_helper.rb +195 -0
- data/lib/common/json_helper.rb +43 -0
- data/lib/common/mock_helper.rb +168 -0
- data/lib/common/mtop_helper.rb +141 -0
- data/lib/common/myconf_helper.rb +49 -0
- data/lib/common/mylog_helper.rb +77 -0
- data/lib/common/pairwise.rb +121 -0
- data/lib/common/query_house.rb +89 -0
- data/lib/common/report_helper.rb +97 -0
- data/lib/common/robot_helper.rb +85 -0
- data/lib/common/socket/check.rb +325 -0
- data/lib/common/socket/conf_modifier.rb +149 -0
- data/lib/common/socket/context.rb +55 -0
- data/lib/common/socket/data.rb +392 -0
- data/lib/common/socket/data_helper.rb +41 -0
- data/lib/common/socket/env.rb +317 -0
- data/lib/common/socket/inc.rb +24 -0
- data/lib/common/socket/log.rb +213 -0
- data/lib/common/socket/log4s.rb +58 -0
- data/lib/common/socket/log_helper.rb +332 -0
- data/lib/common/socket/my_sql.rb +77 -0
- data/lib/common/socket/net.rb +74 -0
- data/lib/common/socket/network.rb +115 -0
- data/lib/common/socket/rlib/conf_modifier.rb +130 -0
- data/lib/common/socket/rlib/data_helper.rb +33 -0
- data/lib/common/socket/rlib/log_helper.rb +303 -0
- data/lib/common/socket/rlib/process_helper.rb +91 -0
- data/lib/common/socket/stub.rb +276 -0
- data/lib/common/socket/util.rb +266 -0
- data/lib/patterns/inc.rb +10 -0
- data/lib/patterns/mc_base_pattern.rb +474 -0
- data/lib/patterns/some_pattern.rb +145 -0
- data/lib/super_test.rb +114 -0
- data/log/super_test.log +0 -0
- data/log/super_test.log.wf +0 -0
- data/test/cover_me.rb +6 -0
- data/tool/jenny +0 -0
- data/tool/mcsend/mcsend2 +0 -0
- data/tool/mcsend/mcsend2_shead +0 -0
- data/tool/mcserver/conf/mcserver.conf +77 -0
- data/tool/mcserver/conf/mcserverauthip +17 -0
- data/tool/mcserver/mcserver +0 -0
- data/tool/mcserver/mcserver_trans +0 -0
- data/tool/mysql +0 -0
- data/tool/net/mcsend/mcsend +0 -0
- data/tool/net/mcsend/mcsend_trans +0 -0
- data/tool/net/mcsend/nshead.data +7 -0
- data/tool/net/mcsend/res_nshead.data +7 -0
- data/tool/net/my_client/my_client +0 -0
- data/tool/net/tsclient/client.tcl +205 -0
- data/tool/others/kk +190 -0
- data/tool/others/rubyatp +42 -0
- data/tool/others/supertest_install.sh +34 -0
- data/tool/trip/idb +0 -0
- data/tool/ts-agent/nshead.bft +12 -0
- data/tool/ts-agent/server.conf +10 -0
- data/tool/ts-agent/server.tcl +376 -0
- metadata +275 -0
@@ -0,0 +1,362 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
#
|
4
|
+
# Author:: hanyu
|
5
|
+
# Date:: 2009.5.7
|
6
|
+
|
7
|
+
|
8
|
+
require 'hpricot'
|
9
|
+
require 'common/http/fix_hpricot'
|
10
|
+
|
11
|
+
# 解析纯文本、HTML、JSON
|
12
|
+
#
|
13
|
+
# - 打印可读日志
|
14
|
+
module HtmlHelper
|
15
|
+
|
16
|
+
# === 功能:
|
17
|
+
# 正则表达式提取
|
18
|
+
#
|
19
|
+
# === 参数解释:
|
20
|
+
# - regexp 提取的正则表达式
|
21
|
+
# - group 正则表达式匹配组号,默认为1
|
22
|
+
#
|
23
|
+
# === Example:
|
24
|
+
# Example #1:
|
25
|
+
#
|
26
|
+
# get "http://www.baidu.com/"
|
27
|
+
# puts find_grep %r"<title>(.*?)</title>"
|
28
|
+
# # => 百度一下,你就知道
|
29
|
+
#
|
30
|
+
# Example #2:
|
31
|
+
#
|
32
|
+
# get "http://www.baidu.com/"
|
33
|
+
# puts find_grep /<title>(.*?),(.*?)<\/title>/, 2
|
34
|
+
# # => 你就知道
|
35
|
+
def find_grep(regexp, group=1)
|
36
|
+
raise "no any http request before!" if @response == nil
|
37
|
+
m = regexp.match @response.body
|
38
|
+
raise HtmlError,"find_grep regexp[#{regexp}] not exist!" if m.nil?
|
39
|
+
return m[group]
|
40
|
+
end
|
41
|
+
|
42
|
+
# === 功能:
|
43
|
+
# 验证是否包含某字符串,不带正则表达式的功能
|
44
|
+
#
|
45
|
+
# === 参数解释:
|
46
|
+
# - str 给定的字符串
|
47
|
+
#
|
48
|
+
# === Example:
|
49
|
+
# Example :
|
50
|
+
# get "http://hi.baidu.com/"
|
51
|
+
# p find_has? "百度空间" #=> true
|
52
|
+
def find_has?(str)
|
53
|
+
raise "no any http request before!" if @response == nil
|
54
|
+
@response.body.include? str
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
# === 功能:
|
60
|
+
# 使用正则表达式的扫描,取出满足的集合
|
61
|
+
#
|
62
|
+
# === 参数解释:
|
63
|
+
# - regexp 扫描的正则表达式
|
64
|
+
# - return 一个二维数组,第一维是匹配上的串,第二维是正则表达式里面的group情况
|
65
|
+
#
|
66
|
+
# === Example:
|
67
|
+
# Example #1: 非block
|
68
|
+
#
|
69
|
+
# get "http://hi.baidu.com/腚腚熊/album"
|
70
|
+
# p find_scan /^imgarr\[len\]=\{purl:"(.*)",psrc:"(.*)",pname:"(.*)",pnum:"(.*)"/
|
71
|
+
# # => [["/%EB%EB%EB%EB%D0%DC/album/%C4%AC%C8%CF%CF%E0%B2%E1", "http://hiphotos.baidu.com/%EB%EB%EB%EB%D0%DC/abpic/item/8ddde41f55e355daa78669b4.jpg", "默认相册", "32"], ["/%EB%EB%EB%EB%D0%DC/album/%CE%D2%B5%C4%D1%D0%BE%BF%C9%FA%CA%B1%B4%FA", "http://hiphotos.baidu.com/%EB%EB%EB%EB%D0%DC/abpic/item/b7c672197f61435542a9ad2f.jpg", "我的研究生时代", "14"], ["/%EB%EB%EB%EB%D0%DC/album/3", "http://hiphotos.baidu.com/%EB%EB%EB%EB%D0%DC/abpic/item/0ded0b80781ddbcb9123d9b2.jpg", "3", "1"], ["/%EB%EB%EB%EB%D0%DC/album/4", "http://hiphotos.baidu.com/%EB%EB%EB%EB%D0%DC/abpic/item/e62608ea188ae1cfd539c991.jpg", "4", "1"], ["/%EB%EB%EB%EB%D0%DC/album/Kongde", "http://hiphotos.baidu.com/%EB%EB%EB%EB%D0%DC/abpic/item/8c3e0aef76094b36acafd5f0.jpg", "Kongde", "0"]]
|
72
|
+
#
|
73
|
+
# Example #2: block方式
|
74
|
+
#
|
75
|
+
# get "http://hi.baidu.com/腚腚熊/album"
|
76
|
+
# find_scan /^imgarr\[len\]=\{purl:"(.*)",psrc:"(.*)",pname:"(.*)",pnum:"(.*)"/ do |url,src,name,num|
|
77
|
+
# p "url:#{url} src:#{src} name:#{name} num:#{num}"
|
78
|
+
# end
|
79
|
+
# # => url:/%EB%EB%EB%EB%D0%DC/album/%C4%AC%C8%CF%CF%E0%B2%E1 src:http://hiphotos.baidu.com/%EB%EB%EB%EB%D0%DC/abpic/item/8ddde41f55e355daa78669b4.jpg name:默认相册 num:32
|
80
|
+
# # => ...
|
81
|
+
def find_scan(regexp,&blk)
|
82
|
+
raise "no any http request before!" if @response == nil
|
83
|
+
return @response.body.scan regexp,&blk
|
84
|
+
end
|
85
|
+
|
86
|
+
# === 功能:
|
87
|
+
# 判断元素是否存在
|
88
|
+
#
|
89
|
+
# === 参数解释:
|
90
|
+
# - xpath 定位,可以使xpath or selector
|
91
|
+
# - return 返回boolean
|
92
|
+
#
|
93
|
+
# === Example:
|
94
|
+
# get "http://www.baidu.com/"
|
95
|
+
# p find_exist? "title" # => true
|
96
|
+
def find_exist?(xpath)
|
97
|
+
raise "no any http request before!" if @response == nil
|
98
|
+
@hpricot ||= Hpricot(@response.body)
|
99
|
+
elems = @hpricot.search(xpath)
|
100
|
+
if block_given?
|
101
|
+
index = -1
|
102
|
+
elems = elems.select do |elem|
|
103
|
+
index = index + 1
|
104
|
+
yield elem,index
|
105
|
+
end
|
106
|
+
end
|
107
|
+
return !elems.empty?
|
108
|
+
end
|
109
|
+
|
110
|
+
# === 功能:
|
111
|
+
# 使用XPath或CSS Selector来提取html片段
|
112
|
+
#
|
113
|
+
# === 参数解释:
|
114
|
+
# - xpath 定位,可以使xpath or selector
|
115
|
+
# - return 返回String
|
116
|
+
#
|
117
|
+
# === Example:
|
118
|
+
# Example #1:
|
119
|
+
#
|
120
|
+
# get "http://www.baidu.com/"
|
121
|
+
# # HTML片段如下
|
122
|
+
# # <p id=km><a href=http://hi.baidu.com>空间</a> <a href=http://www.hao123.com>hao123</a>
|
123
|
+
# # | <a href=/more/>更多<span style="font-family:宋体">>></span></a></p>
|
124
|
+
#
|
125
|
+
# puts find_html "p#km"
|
126
|
+
# # <a href=http://hi.baidu.com>空间</a> <a href=http://www.hao123.com>hao123</a>
|
127
|
+
# # | <a href=/more/>更多<span style="font-family:宋体">>></span></a>
|
128
|
+
#
|
129
|
+
# puts find_html "//p[@id='km']"
|
130
|
+
# # 与上同
|
131
|
+
def find_html(xpath)
|
132
|
+
raise "no any http request before!" if @response == nil
|
133
|
+
@hpricot ||= Hpricot(@response.body)
|
134
|
+
elems = @hpricot.search(xpath)
|
135
|
+
if block_given?
|
136
|
+
index = -1
|
137
|
+
elems = elems.select do |elem|
|
138
|
+
index = index + 1
|
139
|
+
yield elem,index
|
140
|
+
end
|
141
|
+
end
|
142
|
+
raise HtmlError, "find_html xpath[#{xpath}] is not exist!" if elems.empty?
|
143
|
+
return elems.first.html.force_encoding "gbk"
|
144
|
+
end
|
145
|
+
|
146
|
+
# === 功能:
|
147
|
+
# 使用XPath或CSS Selector来提取text内容,不会包含HTML标签
|
148
|
+
#
|
149
|
+
# === 参数解释:
|
150
|
+
# - xpath 定位,可以使xpath or selector
|
151
|
+
# - return 返回String
|
152
|
+
#
|
153
|
+
# === Example:
|
154
|
+
# Example #1:
|
155
|
+
#
|
156
|
+
# get "http://www.baidu.com/"
|
157
|
+
# # HTML片段如下
|
158
|
+
# # <p id=km><a href=http://hi.baidu.com>空间</a>
|
159
|
+
# # <a href=http://www.hao123.com>hao123</a> | <a href=/more/>更多<span style="font-family:宋体">
|
160
|
+
# # >></span></a></p>
|
161
|
+
#
|
162
|
+
# puts find_text "p#km"
|
163
|
+
# # => 空间 hao123 | 更多>>
|
164
|
+
#
|
165
|
+
# puts find_text "//p[@id='km']"
|
166
|
+
# # 与上同
|
167
|
+
def find_text(xpath)
|
168
|
+
raise "no any http request before!" if @response == nil
|
169
|
+
@hpricot ||= Hpricot(@response.body)
|
170
|
+
elems = @hpricot.search(xpath)
|
171
|
+
if block_given?
|
172
|
+
index = -1
|
173
|
+
elems = elems.select do |elem|
|
174
|
+
index = index + 1
|
175
|
+
yield elem,index
|
176
|
+
end
|
177
|
+
end
|
178
|
+
raise HtmlError, "find_html xpath[#{xpath}] is not exist!" if elems.empty?
|
179
|
+
return elems.first.inner_text
|
180
|
+
end
|
181
|
+
|
182
|
+
# === 功能:
|
183
|
+
# 使用XPath或CSS Selector来提取HTML元素的属性值
|
184
|
+
#
|
185
|
+
# === 参数解释:
|
186
|
+
# - xpath 定位,可以使xpath or selector
|
187
|
+
# - attr 属性名
|
188
|
+
# - return 返回String
|
189
|
+
#
|
190
|
+
# === Example:
|
191
|
+
# Example #1:
|
192
|
+
#
|
193
|
+
# get "http://www.baidu.com/"
|
194
|
+
# # HTML片段如下
|
195
|
+
# # <p id=km><a href=http://hi.baidu.com>空间</a> <a href=http://www.hao123.com>hao123</a> | <a href=/more/>更多<span style="font-family:宋体">>></span></a></p>
|
196
|
+
#
|
197
|
+
# puts find_attr "p#km a:first", "href"
|
198
|
+
# # => http://hi.baidu.com
|
199
|
+
def find_attr(xpath, attr)
|
200
|
+
raise "no any http request before!" if @response == nil
|
201
|
+
@hpricot ||= Hpricot(@response.body)
|
202
|
+
elems = @hpricot.search(xpath)
|
203
|
+
if block_given?
|
204
|
+
index = -1
|
205
|
+
elems = elems.select do |elem|
|
206
|
+
index = index + 1
|
207
|
+
yield elem,index
|
208
|
+
end
|
209
|
+
end
|
210
|
+
raise HtmlError, "find_attr xpath[#{xpath}] is not exist!" if elems.empty?
|
211
|
+
elem = elems.first
|
212
|
+
raise HtmlError, "find_attr xpath[#{xpath}] ok, but elem[#{elem}] has no attr[#{attr}]!" unless elem.has_attribute? attr
|
213
|
+
return elem.get_attribute(attr)
|
214
|
+
end
|
215
|
+
|
216
|
+
# === 功能:
|
217
|
+
# 此方法不推荐使用,请使用 find_attr
|
218
|
+
def find_raw_attr(xpath, attr)
|
219
|
+
raise "no any http request before!" if @response == nil
|
220
|
+
@hpricot ||= Hpricot(@response.body)
|
221
|
+
elems = @hpricot.search(xpath.downcase)
|
222
|
+
if block_given?
|
223
|
+
index = -1
|
224
|
+
elems = elems.select do |elem|
|
225
|
+
index = index + 1
|
226
|
+
yield elem,index
|
227
|
+
end
|
228
|
+
end
|
229
|
+
raise HtmlError, "find_attr xpath[#{xpath}] is not exist!" if elems.empty?
|
230
|
+
elem = elems.first
|
231
|
+
raise HtmlError, "find_attr xpath[#{xpath}] ok, but elem[#{elem}] has no attr[#{attr}]!" unless elem.has_attribute? attr
|
232
|
+
return elem.raw_attributes[attr]
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
# === 功能:
|
237
|
+
# 使用XPath或CSS Selector来提取HTML元素集合的个数
|
238
|
+
#
|
239
|
+
# === 参数解释:
|
240
|
+
# - xpath 定位,可以使xpath or selector
|
241
|
+
# - return 返回Fixnum
|
242
|
+
#
|
243
|
+
# === Example:
|
244
|
+
# Example #1:
|
245
|
+
#
|
246
|
+
# get "http://www.baidu.com/"
|
247
|
+
# # HTML片段如下
|
248
|
+
# # <p id=km><a href=http://hi.baidu.com>空间</a> <a href=http://www.hao123.com>hao123</a> | <a href=/more/>更多<span style="font-family:宋体">>></span></a></p>
|
249
|
+
#
|
250
|
+
# puts find_size "p#km a"
|
251
|
+
# # => 3
|
252
|
+
# # 上层的意义可能是“输入框下面这一行显示3个超链接
|
253
|
+
def find_size(xpath)
|
254
|
+
raise "no any http request before!" if @response == nil
|
255
|
+
@hpricot ||= Hpricot(@response.body)
|
256
|
+
elems = @hpricot.search(xpath)
|
257
|
+
if block_given?
|
258
|
+
index = -1
|
259
|
+
elems = elems.select do |elem|
|
260
|
+
index = index + 1
|
261
|
+
yield elem,index
|
262
|
+
end
|
263
|
+
end
|
264
|
+
return elems.size
|
265
|
+
end
|
266
|
+
|
267
|
+
# 使用XPath或CSS Selector来提取HTML元素集合的个数
|
268
|
+
#
|
269
|
+
# === 参数解释:
|
270
|
+
# - xpath 父亲节点,可以使xpath or selector
|
271
|
+
# - excludes 排除的子节点名,长度可变参数
|
272
|
+
# - RETURN 返回非elems内的儿子节点集合
|
273
|
+
#
|
274
|
+
# === Example:
|
275
|
+
# get "http://hi.baidu.com/sys/search?word=我&from=wise"
|
276
|
+
# p find_children("entry > list > blog:first")
|
277
|
+
# #=> ["title", "content", "spsspaceurlorilist", "url", "time", "spsspacenamelist"]
|
278
|
+
# p find_children("entry > list > blog:first",%w{title content url time spsSpaceURLOriList})
|
279
|
+
# #=> ["spsspacenamelist"]
|
280
|
+
def find_children(xpath,excludes=[])
|
281
|
+
raise "no any http request before!" if @response == nil
|
282
|
+
@hpricot ||= Hpricot(@response.body)
|
283
|
+
elems = @hpricot.search(xpath)
|
284
|
+
if block_given?
|
285
|
+
index = -1
|
286
|
+
elems = elems.select do |elem|
|
287
|
+
index = index + 1
|
288
|
+
yield elem,index
|
289
|
+
end
|
290
|
+
end
|
291
|
+
raise HtmlError, "find_attr xpath[#{xpath}] is not exist!" if elems.empty?
|
292
|
+
elem = elems.first
|
293
|
+
|
294
|
+
rs = []
|
295
|
+
elem.children.each do |el|
|
296
|
+
if el.class == Hpricot::Elem and !excludes.include?(el.name)
|
297
|
+
rs << el.name
|
298
|
+
end
|
299
|
+
end
|
300
|
+
return rs
|
301
|
+
end
|
302
|
+
|
303
|
+
|
304
|
+
# === 功能:
|
305
|
+
# 高级接口,将 Hpricot 暴露出来,请参看 Hpricot 的使用手册
|
306
|
+
# 返回数组
|
307
|
+
#
|
308
|
+
# === 参数解释:
|
309
|
+
# - xpath 定位,可以使xpath or selector
|
310
|
+
# - return 返回Hpricot::Elems
|
311
|
+
#
|
312
|
+
# === Example:
|
313
|
+
# get "http://www.baidu.com"
|
314
|
+
# hpricot_search("div").each |elem|
|
315
|
+
# p elem
|
316
|
+
# end
|
317
|
+
def hpricot_search(xpath, &blk)
|
318
|
+
raise "no any http request before!" if @response == nil
|
319
|
+
@hpricot ||= Hpricot(@response.body)
|
320
|
+
@hpricot.search(xpath, &blk)
|
321
|
+
end
|
322
|
+
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
|
327
|
+
#
|
328
|
+
class HtmlError < StandardError
|
329
|
+
# TODO
|
330
|
+
end
|
331
|
+
|
332
|
+
|
333
|
+
if __FILE__ == $0
|
334
|
+
p __FILE__
|
335
|
+
p $0
|
336
|
+
class MyTest
|
337
|
+
include HtmlHelper
|
338
|
+
|
339
|
+
# 高级接口,将 Hpricot 暴露出来
|
340
|
+
def hpricot_search(xpath, &blk)
|
341
|
+
@hpricot ||= Hpricot("<tr><td>111</td><td id='q'>222</td><br/><td>333</td></tr>")
|
342
|
+
@hpricot.search(xpath, &blk)
|
343
|
+
end
|
344
|
+
def test
|
345
|
+
#post("http://passport.baidu.com/?login","username=hannyu5122&password=aaaa")
|
346
|
+
h = Hpricot("<tr><td>111</td><td id='q'>222</td><br/><td>333</td></tr>")
|
347
|
+
p h.search("tr td").text
|
348
|
+
p h.search("tr td#q").html
|
349
|
+
p h.search("tr td#q")[0]
|
350
|
+
p h.search("tr td#q")[0].next.html
|
351
|
+
p h.search("tr td")[0].get_attribute("id")
|
352
|
+
p h.search("tr td")[0].inner_text
|
353
|
+
p h.search("tr td#q")[0].html
|
354
|
+
p h.search("tt td")
|
355
|
+
p h.search("td").size
|
356
|
+
p h.search("tt td")[0].html
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|
360
|
+
MyTest.new.test2
|
361
|
+
end
|
362
|
+
|
@@ -0,0 +1,469 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
#
|
4
|
+
# Author:: hanyu
|
5
|
+
# Date:: 2009.5.7
|
6
|
+
|
7
|
+
require 'net/http'
|
8
|
+
require 'net/https'
|
9
|
+
require 'cgi'
|
10
|
+
require 'uri'
|
11
|
+
require 'webrick'
|
12
|
+
require "common/http/multipart"
|
13
|
+
|
14
|
+
# 实现HTTP协议的支持,可以在action或case中调用
|
15
|
+
#
|
16
|
+
# - 封装 Net:HTTP 和 Net:HTTPS
|
17
|
+
# - 模拟浏览器的Cookie策略,不完全实现,不支持Expire(没必要)
|
18
|
+
# - 上下文环境的保持,request & response
|
19
|
+
# - 编码转换(统一使用gbk)
|
20
|
+
# - Referer、User-Agent等的自动填入
|
21
|
+
# - 打印可读日志
|
22
|
+
module HttpHelper
|
23
|
+
|
24
|
+
# === 功能:
|
25
|
+
# 发送POST请求
|
26
|
+
#
|
27
|
+
# === 参数解释:
|
28
|
+
# - url http请求的url,比如: http://hi.baidu.com/,前面的http和后面的/都不能省略
|
29
|
+
# - data post的数据,Hash格式,键可以是字符串或符号,值可以是字符串或其他
|
30
|
+
# - header http请求携带的header,比如referer、p3p等,形式与data类似
|
31
|
+
# - file 支持上传文件,可以传多个,Hash格式,键为参数名,值为文件的本地路径
|
32
|
+
#
|
33
|
+
# === Example:
|
34
|
+
# Example #1:
|
35
|
+
# # 模拟登录
|
36
|
+
# post "http://passport.baidu.com/?login", {
|
37
|
+
# :username => 'xxx',
|
38
|
+
# :password => 'yyy'
|
39
|
+
# }
|
40
|
+
#
|
41
|
+
# Example #2:
|
42
|
+
# # 自定义header
|
43
|
+
# login user
|
44
|
+
# post "http://hi.baidu.com/xxx/commit", {
|
45
|
+
# :ct => 1,
|
46
|
+
# :cm => 2,
|
47
|
+
# ........
|
48
|
+
# }, {
|
49
|
+
# "Myhead" => "okoko"
|
50
|
+
# }
|
51
|
+
#
|
52
|
+
# Example #3:
|
53
|
+
# post "http://hi.baidu.com/upload",{
|
54
|
+
# :xxx => 'yyy'
|
55
|
+
# }
|
56
|
+
# # 环境变量的注入
|
57
|
+
# puts @request.method
|
58
|
+
# puts @response.body
|
59
|
+
# puts @response.header["Content-Length"]
|
60
|
+
# puts @cookies
|
61
|
+
#
|
62
|
+
# Example #4:
|
63
|
+
# # 上传文件
|
64
|
+
# post "http://hi.baidu.com/upload",{
|
65
|
+
# :xxx => 'yyy'
|
66
|
+
# },{},{
|
67
|
+
# "param_name" => "file_path"
|
68
|
+
# }
|
69
|
+
#
|
70
|
+
def post(url,data={},header={},file={})
|
71
|
+
#解析成URI
|
72
|
+
$myparse = $myparse || URI::Parser.new(:RESERVED=>URI::REGEXP::PATTERN::RESERVED+"%")
|
73
|
+
uri = $myparse.parse $myparse.escape(url)
|
74
|
+
raise HttpError, "url[#{url}] parse fail! e.g. http://hi.baidu.com/" if uri.scheme.nil? or uri.host.nil? or uri.path.empty?
|
75
|
+
|
76
|
+
# CGI:URI.path 需要加上query部分才能构成一个正常的请求
|
77
|
+
path = (uri.query==nil) ? uri.path : uri.path+"?"+uri.query
|
78
|
+
|
79
|
+
# 把header符号变成字符串
|
80
|
+
header.each do |k,v|
|
81
|
+
if k.class == Symbol
|
82
|
+
header[k.to_s] = v.to_s
|
83
|
+
header.delete k
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# 初始化Post请求
|
88
|
+
req = Net::HTTP::Post.new(path, header)
|
89
|
+
req.set_content_type "application/x-www-form-urlencoded" unless req.content_type
|
90
|
+
|
91
|
+
# 发送请求
|
92
|
+
send_http req,uri,data,file
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# === 功能:
|
97
|
+
# 发送GET请求
|
98
|
+
#
|
99
|
+
# === 参数解释:
|
100
|
+
# - url http请求的url,比如: http://hi.baidu.com/,前面的http和后面的/都不能省略
|
101
|
+
# - data 数据将被编码并附在url的后面,Hash格式,键可以是字符串或符号,值可以是字符串或其他
|
102
|
+
# - header http请求携带的header,比如referer、p3p等,形式与data类似
|
103
|
+
#
|
104
|
+
# === Example:
|
105
|
+
# Example #1:
|
106
|
+
# # 注意url要写全,带上协议头"http",以及路径,若是根路径末尾要加"/"
|
107
|
+
# get "http://www.baidu.com/"
|
108
|
+
#
|
109
|
+
# Example #2:
|
110
|
+
# # 支持https
|
111
|
+
# get "https://passport.baidu.com/"
|
112
|
+
#
|
113
|
+
# Example #3:
|
114
|
+
# get "http://www.baidu.com/"
|
115
|
+
# # 环境变量的注入
|
116
|
+
# puts @request.method
|
117
|
+
# puts @response.body
|
118
|
+
# puts @response.header["Content-Length"]
|
119
|
+
# puts @cookies
|
120
|
+
#
|
121
|
+
# Example #4:
|
122
|
+
# # 可自定义 HTTP Header
|
123
|
+
# get "http://hi.baidu.com/",{
|
124
|
+
# :q => "空间",
|
125
|
+
# :t => "haha"
|
126
|
+
# },{
|
127
|
+
# "Cookie" => "BDUSS=xxx;",
|
128
|
+
# "Referer" => "google.com"
|
129
|
+
# }
|
130
|
+
#
|
131
|
+
# Example #5:
|
132
|
+
# # 带参数
|
133
|
+
# get "https://passport.baidu.com/",{
|
134
|
+
# :name => "walle",
|
135
|
+
# :password => "1111"
|
136
|
+
# }
|
137
|
+
#
|
138
|
+
def get(url,data={},header={})
|
139
|
+
#解析成URI
|
140
|
+
$myparse = $myparse || URI::Parser.new(:RESERVED=>URI::REGEXP::PATTERN::RESERVED+"%")
|
141
|
+
uri = $myparse.parse $myparse.escape(url)
|
142
|
+
raise HttpError, "url[#{url}] parse fail! e.g. http://hi.baidu.com/" if uri.scheme.nil? or uri.host.nil? or uri.path.empty?
|
143
|
+
|
144
|
+
# CGI:URI.path 需要加上query部分才能构成一个正常的请求
|
145
|
+
path = (uri.query==nil) ? uri.path : uri.path+"?"+uri.query
|
146
|
+
|
147
|
+
# 将data转成url中的参数
|
148
|
+
path << "?" if data.size>0 && !path.include?("?")
|
149
|
+
data.each do |k,v|
|
150
|
+
path << "&" if !path.end_with?("&") && !path.end_with?("?")
|
151
|
+
path << k.to_s + "=" + CGI::escape(v.to_s)
|
152
|
+
end
|
153
|
+
|
154
|
+
# 把header符号变成字符串
|
155
|
+
header.each do |k,v|
|
156
|
+
if k.class == Symbol
|
157
|
+
header[k.to_s] = v.to_s
|
158
|
+
header.delete k
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# 初始化Get请求
|
163
|
+
req = Net::HTTP::Get.new(path, header)
|
164
|
+
|
165
|
+
# 发送请求
|
166
|
+
send_http req,uri
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
def download(uri, path=nil)
|
171
|
+
begin
|
172
|
+
if path
|
173
|
+
file_name = path + uri.split('/').last
|
174
|
+
file_name.sub(/\/\//, '/')
|
175
|
+
else
|
176
|
+
file_name = uri.split('/').last
|
177
|
+
end
|
178
|
+
|
179
|
+
file_content = get uri
|
180
|
+
#puts file_name
|
181
|
+
File.open(file_name, "w+") do |file|
|
182
|
+
file.binmode # must be in binary mode
|
183
|
+
file.write file_content
|
184
|
+
file.rewind
|
185
|
+
end
|
186
|
+
rescue => err
|
187
|
+
puts err
|
188
|
+
return ''
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# === 功能:
|
193
|
+
# 发送PUT请求
|
194
|
+
# 未实现,有需求吗?
|
195
|
+
#
|
196
|
+
# === 参数解释:
|
197
|
+
#
|
198
|
+
# === Example:
|
199
|
+
#
|
200
|
+
def put(url,data="",header=nil,file=nil)
|
201
|
+
#TODO
|
202
|
+
end
|
203
|
+
|
204
|
+
# === 功能:
|
205
|
+
# 发送DELETE请求
|
206
|
+
# 未实现,有需求吗?
|
207
|
+
#
|
208
|
+
# === 参数解释:
|
209
|
+
#
|
210
|
+
# === Example:
|
211
|
+
#
|
212
|
+
def delete(url,data=nil,header=nil)
|
213
|
+
#TODO
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
# === 功能:
|
218
|
+
# 清空当前cookie
|
219
|
+
#
|
220
|
+
# === 参数解释:
|
221
|
+
#
|
222
|
+
# === Example:
|
223
|
+
# get "http://www.baidu.com/"
|
224
|
+
# clear_cookie # => 清空cookie
|
225
|
+
# get "http://hi.baidu.com/"
|
226
|
+
def clear_cookie
|
227
|
+
@cookies = {}
|
228
|
+
end
|
229
|
+
|
230
|
+
# === 功能:
|
231
|
+
# 指定不要进行转码
|
232
|
+
#
|
233
|
+
# === 参数解释:
|
234
|
+
#
|
235
|
+
# === Example:
|
236
|
+
# Example #1: block方式
|
237
|
+
#
|
238
|
+
# dont_encode do
|
239
|
+
# get "..."
|
240
|
+
# post "..."
|
241
|
+
# end
|
242
|
+
# # 凡是块里面的请求都不会有转码,但是块外面的代码仍然可以
|
243
|
+
#
|
244
|
+
# Example #2: 非block方式
|
245
|
+
#
|
246
|
+
# get "http://www.baidu.com/"
|
247
|
+
# # 返回页面经过转码,转成GBK
|
248
|
+
# dont_encode
|
249
|
+
# get "http://www.baidu.com/"
|
250
|
+
# # 返回页面在任何情况下都不会做任何转码
|
251
|
+
# # ...
|
252
|
+
# do_encode
|
253
|
+
# # 恢复转码方式
|
254
|
+
# get "http://www.baidu.com/"
|
255
|
+
# # 返回页面经过转码,转成GBK
|
256
|
+
def dont_encode
|
257
|
+
if block_given?
|
258
|
+
@dont_encode = true
|
259
|
+
yield
|
260
|
+
@dont_encode = false
|
261
|
+
else
|
262
|
+
@dont_encode = true
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# === 功能:
|
267
|
+
# 参见dont_encode
|
268
|
+
def do_encode
|
269
|
+
if block_given?
|
270
|
+
@dont_encode = false
|
271
|
+
yield
|
272
|
+
@dont_encode = true
|
273
|
+
else
|
274
|
+
@dont_encode = false
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
# === 功能:
|
279
|
+
# 打印当前HTTP请求返回的content,可用于调试
|
280
|
+
#
|
281
|
+
# === 参数解释:
|
282
|
+
# 无
|
283
|
+
#
|
284
|
+
# === Example:
|
285
|
+
# get "http://www.baidu.com/"
|
286
|
+
# print_body
|
287
|
+
# #=> <html><head><meta http-equiv=Content-Type content="text/html;charset=gb2312"><title>百度一下,你就知道 </title>.....(省略)
|
288
|
+
#
|
289
|
+
def print_body
|
290
|
+
puts @response.body unless @response.nil?
|
291
|
+
end
|
292
|
+
|
293
|
+
# === 功能:
|
294
|
+
# 打印当前HTTP请求返回的所有Header,可用于调试
|
295
|
+
#
|
296
|
+
# === 参数解释:
|
297
|
+
# 无
|
298
|
+
#
|
299
|
+
# === Example:
|
300
|
+
# get "http://www.baidu.com/"
|
301
|
+
# print_head
|
302
|
+
# #=> {"date"=>["Sun, 27 Dec 2009 12:04:29 GMT"], "server"=>["BWS/1.0"], "content-length"=>["3657"], "content-type"=>["text/html;charset=gb2312"], "cache-control"=>["private"], "expires"=>["Sun, 27 Dec 2009 12:04:29 GMT"], "set-cookie"=>["BAIDUID=95C50755A927A287A68E2014CEF4CF1E:FG=1; expires=Sun, 27-Dec-39 12:04:29 GMT; path=/; domain=.baidu.com"], "p3p"=>["CP=\" OTI DSP COR IVA OUR IND COM \""]}
|
303
|
+
#
|
304
|
+
def print_head
|
305
|
+
puts @response.to_hash unless @response.nil?
|
306
|
+
end
|
307
|
+
alias print_header print_head
|
308
|
+
|
309
|
+
# 以下方法为私有
|
310
|
+
private
|
311
|
+
|
312
|
+
# 封装发送HTTP细节
|
313
|
+
def send_http(req,uri,data=nil,file={})
|
314
|
+
#注入上下文环境中的cookie
|
315
|
+
@cookies = {} if @cookies.nil?
|
316
|
+
@cookies.each do |key,coos|
|
317
|
+
if uri.host.end_with? key
|
318
|
+
coos.each do |coo|
|
319
|
+
if req.key? "cookie"
|
320
|
+
req["cookie"] += "#{coo.name}=#{coo.value};"
|
321
|
+
else
|
322
|
+
req["cookie"] = "#{coo.name}=#{coo.value};"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
# 填入默认header
|
329
|
+
# req["User-Agent"] = "#{ConfigHelper::CONF['user_agent']}" if req["User-Agent"] == "Ruby"
|
330
|
+
# req["Referer"] = "#{@referer}" unless req.key? "referer"
|
331
|
+
|
332
|
+
# 如果上传文件,需要Multipart的支持
|
333
|
+
if file.size > 0
|
334
|
+
file.each do |k,v|
|
335
|
+
file[k] = File.new v
|
336
|
+
end
|
337
|
+
data_str, headers = Multipart::Post.prepare_query data.merge(file)
|
338
|
+
req["Content-Type"] = headers["Content-Type"]
|
339
|
+
else
|
340
|
+
#转义data
|
341
|
+
if data.nil?
|
342
|
+
data_str = nil
|
343
|
+
elsif data.kind_of? Hash
|
344
|
+
data_str = data.inject("") do |mem, (key, value)|
|
345
|
+
mem << "&" if mem.size > 0
|
346
|
+
mem << key.to_s + "=" + CGI::escape(value.to_s)
|
347
|
+
end
|
348
|
+
else
|
349
|
+
raise "data must be Hash"
|
350
|
+
end
|
351
|
+
|
352
|
+
end
|
353
|
+
|
354
|
+
#如果是HTTPS 安全连接
|
355
|
+
conn = Net::HTTP.new(uri.host, uri.port)
|
356
|
+
if uri.scheme == "https"
|
357
|
+
conn.use_ssl = true
|
358
|
+
conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
359
|
+
end
|
360
|
+
|
361
|
+
take = 0
|
362
|
+
#加入异常捕获机器
|
363
|
+
begin
|
364
|
+
ts1 = Time.now
|
365
|
+
#发送HTTP请求
|
366
|
+
res = conn.start do |http|
|
367
|
+
#puts "data_str.size: #{data_str.size}" unless data_str.nil?
|
368
|
+
http.request(req,data_str)
|
369
|
+
end
|
370
|
+
ts2 = Time.now
|
371
|
+
take = ts2 - ts1
|
372
|
+
rescue SocketError => err
|
373
|
+
#域名不能解析,机器下线?
|
374
|
+
$log.error "#{req.method} url[#{uri}] data[#{data}] file[#{file}] time[#{take}s] FAIL! Host[#{uri.host}] is unknown! Maybe it is out of the DNS."
|
375
|
+
raise HttpError, "host[#{uri.host}] is unknown! Maybe it is out of the DNS."
|
376
|
+
rescue EOFError => err
|
377
|
+
#连接被中断,被transmit拒?
|
378
|
+
$log.error "#{req.method} url[#{uri}] data[#{data}] file[#{file}] time[#{take}s] FAIL! Connection with uri[#{uri}] is interrupted! Maybe transmit did this."
|
379
|
+
raise HttpError, "Connection with uri[#{uri}] is interrupted! Maybe transmit did this."
|
380
|
+
rescue SystemCallError => err
|
381
|
+
#服务被拒绝,端口未开放?
|
382
|
+
$log.error "#{req.method} url[#{uri}] data[#{data}] file[#{file}] time[#{take}s] FAIL! Connection with uri[#{uri}] is refused! Maybe the port[#{uri.port}] is not open."
|
383
|
+
raise HttpError, "Connection with uri[#{uri}] is refused! Maybe the port[#{uri.port}] is not open."
|
384
|
+
end
|
385
|
+
#将返回的cookie存入上下文环境中
|
386
|
+
if res.key?('set-cookie')
|
387
|
+
res.get_fields('set-cookie').each do |str|
|
388
|
+
cookie = WEBrick::Cookie.parse_set_cookie(str)
|
389
|
+
cookie.domain = uri.host if cookie.domain == nil
|
390
|
+
if @cookies.key?(cookie.domain)
|
391
|
+
@cookies[cookie.domain].delete_if do |coo|
|
392
|
+
coo.name == cookie.name
|
393
|
+
end
|
394
|
+
@cookies[cookie.domain] << cookie if cookie.value != "deleted"
|
395
|
+
else
|
396
|
+
@cookies[cookie.domain] = [cookie]
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
#置上下文变量
|
402
|
+
@referer = uri.to_s
|
403
|
+
@request = req
|
404
|
+
@response = res
|
405
|
+
@hpricot = nil
|
406
|
+
|
407
|
+
# #编码转换
|
408
|
+
# unless res.body.nil? or
|
409
|
+
# @dont_encode or
|
410
|
+
# res["Content-Type"].nil? or # 如果没有 content-type 字段,那么不做转换
|
411
|
+
# res["Content-Type"].include? "image" or # 图片不转
|
412
|
+
# res["Content-Type"].include? "video" or # 视频不转
|
413
|
+
# res["Content-Type"].include? "audio" # 声音不转
|
414
|
+
# ct = res["Content-Type"].scan(/charset=(.*?);?$/)[0]
|
415
|
+
# encod = ct[0].downcase unless ct.nil?
|
416
|
+
# if ! encod.nil?
|
417
|
+
# if encod=="gbk" or encod=="gb2312"
|
418
|
+
# res.body = res.body.force_encoding("gbk")
|
419
|
+
# else
|
420
|
+
# res.body = res.body.force_encoding(encod).encode "gbk"
|
421
|
+
# end
|
422
|
+
# else
|
423
|
+
# if ConfigHelper::CONF["default_encoding"]=="gbk"
|
424
|
+
# res.body = res.body.force_encoding("gbk")
|
425
|
+
# else
|
426
|
+
# res.body = res.body.force_encoding(ConfigHelper::CONF["default_encoding"]).encode "gbk"
|
427
|
+
# end
|
428
|
+
# end
|
429
|
+
# end
|
430
|
+
res.body
|
431
|
+
end
|
432
|
+
|
433
|
+
end
|
434
|
+
|
435
|
+
class HttpError < StandardError
|
436
|
+
# do nothing
|
437
|
+
end
|
438
|
+
|
439
|
+
|
440
|
+
|
441
|
+
if __FILE__ == $0
|
442
|
+
$LIB_ROOT = "#{File.dirname(__FILE__)}/.."
|
443
|
+
$TEST_ROOT = "#{$LIB_ROOT}/.."
|
444
|
+
$: << "#{$LIB_ROOT}"
|
445
|
+
require 'common/log_helper'
|
446
|
+
require 'common/config_helper'
|
447
|
+
|
448
|
+
class MyTest
|
449
|
+
include HttpHelper
|
450
|
+
|
451
|
+
def test1
|
452
|
+
@cookies = {}
|
453
|
+
#post("http://passport.baidu.com/?login","username=hannyu5122&password=aaaa")
|
454
|
+
get "http://www.baidu.com/"
|
455
|
+
puts @response.body
|
456
|
+
get "http://sz-testing-space07.sz01.baidu.com:5120/haoba?oko"
|
457
|
+
end
|
458
|
+
def test2
|
459
|
+
@cookies = {}
|
460
|
+
assert_raise HttpError do
|
461
|
+
get "http://db-testing-space13.db01.baidu.com:4444/developers"
|
462
|
+
#get "http://db-testing-space13.db01.baidu.com:8080/developers"
|
463
|
+
get "http://db-testing-sp.db01.baidu.com:8080/developers"
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
MyTest.new.test2
|
468
|
+
end
|
469
|
+
|