milk1000cc-web_service_simple 0.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.
data/README.textile ADDED
@@ -0,0 +1,127 @@
1
+ h1. WebService::Simple
2
+
3
+ Simple Interface To Web Services APIs (Ruby)
4
+
5
+ "Original perl version":http://search.cpan.org/~yusukebe/WebService-Simple-0.15/lib/WebService/Simple.pm was created by Yusuke Wada.
6
+
7
+ h2. Usage
8
+
9
+ <pre>
10
+ require 'rubygems'
11
+ require 'web_service_simple'
12
+
13
+ # Simple use case
14
+ technorati = WebService::Simple.new(
15
+ :base_url => 'http://api.technorati.com/',
16
+ :param => { :key => 'your_api_key', }
17
+ )
18
+
19
+ # send GET request to
20
+ # http://api.technorati.com/?language=ja&key=your_api_key&query=value
21
+ technorati.get :language => 'ja', :query => 'value'
22
+
23
+ # send GET request to
24
+ # http://api.technorati.com/extra/path?language=ja&key=your_api_key&query=value
25
+ technorati.get 'extra/path', :language => 'ja', :query => 'value'
26
+ </pre>
27
+
28
+ h2. Methods
29
+
30
+ * new(arg)
31
+
32
+ <pre>
33
+ technorati = WebService::Simple.new(
34
+ :base_url => 'http://api.technorati.com/',
35
+ :param => { :key => 'your_api_key', },
36
+ # :debug => 1
37
+ )
38
+ </pre>
39
+
40
+ Create and return a new WebService::Simple object. "new" Method requires a base_url of Web Service API. If debug is set, dump a request URL in get or post method.
41
+
42
+ * get([extra_path,] arg)
43
+
44
+ <pre>
45
+ response =
46
+ technorati.get(:language => 'ja', :query => 'value')
47
+ </pre>
48
+
49
+ Send GET request, and you can get the WebService::Simple::Response object. If you want to add a path to base URL, use an option parameter.
50
+
51
+ <pre>
52
+ technorati = WebService::Simple.new(
53
+ :base_url => 'http://api.technorati.com/',
54
+ :param => { :api_key => 'your_api_key', :language => 'ja' }
55
+ )
56
+ response = technorati.get('search', :limit => 50)
57
+ </pre>
58
+
59
+ * base_url
60
+
61
+ * base_url=
62
+
63
+ * basic_params
64
+
65
+ * basic_params=
66
+
67
+ * logger
68
+
69
+ * logger=
70
+
71
+ * debug
72
+
73
+ * debug=
74
+
75
+ * response_parser
76
+
77
+ * response_parser=
78
+
79
+ h2. Subclassing
80
+
81
+ For better encapsulation, you can create subclass of WebService::Simple to customize the behavior
82
+
83
+ <pre>
84
+ class WebService::Simple::Technorati < WebService::Simple
85
+ @@config = {
86
+ :base_url => 'http://api.technorati.jp',
87
+ :response_parser => { :module => 'XML::Technorati' }
88
+ }
89
+
90
+ def key_info
91
+ get '/keyinfo'
92
+ end
93
+
94
+ def search(keyword)
95
+ get '/search', :query => keyword
96
+ end
97
+ end
98
+ </pre>
99
+
100
+ h2. Parsers
101
+
102
+ Web services return their results in various different formats. Or perhaps you require more sophisticated results parsing than what WebService::Simple provides.
103
+
104
+ WebService::Simple by default uses WebService::Simple::Parser::XML::Nokogiri (based on Nokogiri gem), but you can easily override that by providing a parser object to the constructor:
105
+
106
+ <pre>
107
+ service = WebService::Simple.new(
108
+ :response_parsrer => AVeryComplexParser.new,
109
+ ...
110
+ )
111
+ response = service.get( ... )
112
+ thing = response.parse_response
113
+ </pre>
114
+
115
+ This allows great flexibility in handling different webservices
116
+
117
+ h2. Install
118
+
119
+ <pre>
120
+ sudo gem install milk1000cc-web_service_simple --source=http://gems.github.com
121
+ </pre>
122
+
123
+ h2. Author
124
+
125
+ milk1000cc &lt;<a href="mailto:info@milk1000.cc">info@milk1000.cc</a>&gt;
126
+
127
+ Yusuke Wada
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'web_service/simple'
@@ -0,0 +1,92 @@
1
+ require 'logger'
2
+ require 'net/http'
3
+ require 'uri'
4
+
5
+ require 'web_service/simple/response'
6
+ require 'web_service/simple/response_code_error'
7
+ require 'web_service/simple/parser'
8
+
9
+ module WebService
10
+ class Simple
11
+ VERSION = '0.0.1'
12
+
13
+ attr_accessor :base_url
14
+ attr_accessor :basic_params
15
+ attr_accessor :response_parser
16
+ attr_accessor :logger
17
+ attr_accessor :debug
18
+
19
+ @@config = {
20
+ :base_url => nil,
21
+ :response_parser => { :module => 'XML::Nokogiri' }
22
+ }
23
+
24
+ def logger
25
+ unless @logger
26
+ @logger = Logger.new(STDOUT)
27
+ @logger.level = Logger::INFO
28
+ end
29
+ @logger
30
+ end
31
+
32
+ def response_parser
33
+ unless @response_parser and @response_parser.is_a?(Parser)
34
+ klass = @response_parser.is_a?(Hash) ? @response_parser[:module] : @response_parser
35
+ klass = "Simple::Parser::#{ klass }"
36
+ require File.expand_path(underscore(klass), File.dirname(__FILE__))
37
+ @response_parser = eval(klass).new
38
+ end
39
+ @response_parser
40
+ end
41
+
42
+ def initialize(arg = {})
43
+ Net::HTTP.version_1_2
44
+
45
+ @base_url = arg[:base_url] || @@config[:base_url]
46
+ raise ArgumentError, 'base_url is required' unless @base_url
47
+
48
+ @logger = arg[:logger]
49
+ @debug = arg[:debug] || false
50
+ @basic_params = arg[:params] || arg[:param] || {}
51
+ @response_parser = arg[:response_parser] || @@config[:response_parser]
52
+ end
53
+
54
+ def get(*args)
55
+ extra_path, extra_params = nil, {}
56
+
57
+ if args.first.is_a?(Hash)
58
+ extra_params = args.shift
59
+ else
60
+ extra_path = args.shift
61
+ extra_params = args.shift if args.first.is_a?(Hash)
62
+ end
63
+
64
+ params = @basic_params.merge(extra_params).map { |k, v| "#{ URI.escape(k.to_s) }=#{ URI.escape(v.to_s) }" } * '&'
65
+ uri = URI("#{ @base_url }#{ extra_path }?#{ params }")
66
+
67
+ log "Request URL is #{ uri }"
68
+
69
+ response = nil
70
+ Net::HTTP.start(uri.host, uri.port) { |http|
71
+ req = Net::HTTP::Get.new(uri.request_uri)
72
+ response = http.request(req)
73
+ }
74
+ raise ResponseCodeError.new(response) unless response.code == '200'
75
+
76
+ Response.new(response.body, response_parser)
77
+ end
78
+
79
+ private
80
+ def underscore(camel_cased_word)
81
+ camel_cased_word.to_s.gsub(/::/, '/').
82
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
83
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
84
+ tr("-", "_").
85
+ downcase
86
+ end
87
+
88
+ def log(message)
89
+ logger.info "[simple_web_service] #{message}" if @debug
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,6 @@
1
+ module WebService
2
+ class Simple
3
+ class Parser
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+
4
+ module WebService
5
+ class Simple
6
+ class Parser
7
+ class JSON < Parser
8
+ def parse_response(response)
9
+ ::JSON.parse response.content
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'nokogiri'
3
+
4
+ module WebService
5
+ class Simple
6
+ class Parser
7
+ module XML
8
+ class Nokogiri < Parser
9
+ def parse_response(response)
10
+ ::Nokogiri::XML response.content
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module WebService
2
+ class Simple
3
+ class Response
4
+ attr_reader :content
5
+
6
+ def initialize(content, parser)
7
+ @content = content
8
+ @parser = parser
9
+ end
10
+
11
+ def parse_response
12
+ @parser.parse_response self
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module WebService
2
+ class Simple
3
+ class ResponseCodeError < RuntimeError
4
+ attr_reader :response_code
5
+ attr_reader :response_body
6
+
7
+ def initialize(response)
8
+ @response_code = response.code
9
+ @response_body = response.body
10
+ end
11
+
12
+ def to_s
13
+ "#{ response_code } => #{ Net::HTTPResponse::CODE_TO_OBJ[response_code] }"
14
+ end
15
+
16
+ def inspect; to_s; end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1 @@
1
+ require 'web_service/simple'
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../lib", File.dirname(__FILE__))
4
+
5
+ require 'rubygems'
6
+ require 'spec'
7
+ require 'fakeweb'
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require File.expand_path('../../../spec_helper', File.dirname(__FILE__))
5
+ require 'web_service/simple/parser'
6
+ require 'web_service/simple/parser/json'
7
+
8
+ describe WebService::Simple::Parser::JSON do
9
+ describe '#parse_response' do
10
+ it 'は、json pure で JSON 文字列をパースして、その結果を返すこと' do
11
+ parser = WebService::Simple::Parser::JSON.new
12
+ response = stub(:response, :content => '{ "hoge": 3, "fuga": ["a", "b"] }')
13
+ parser.parse_response(response).should == { 'hoge' => 3, 'fuga' => ['a', 'b'] }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require File.expand_path('../../../../spec_helper', File.dirname(__FILE__))
5
+ require 'web_service/simple/parser'
6
+ require 'web_service/simple/parser/xml/nokogiri'
7
+
8
+ describe WebService::Simple::Parser::XML::Nokogiri do
9
+ before do
10
+ @xml = <<-'EOF'
11
+ <?xml version="1.0" encoding="UTF-8"?>
12
+ <!-- generator="Technorati API version 1.0" -->
13
+ <!DOCTYPE tapi PUBLIC "-//Technorati, Inc.//DTD TAPI 0.02//EN" "http://api.technorati.com/dtd/tapi-002.xml">
14
+ <tapi version="1.0">
15
+ <document>
16
+ <result>
17
+ <query>ミッドナイトクラブ</query>
18
+ <total>109</total>
19
+ <start/>
20
+ </result>
21
+ </document>
22
+ </tapi>
23
+ EOF
24
+ end
25
+
26
+ describe '#parse_response' do
27
+ it 'は、nokogiri で xml をパースして、その結果を返すこと' do
28
+ parser = WebService::Simple::Parser::XML::Nokogiri.new
29
+ response = stub(:response, :content => @xml)
30
+ parser.parse_response(response).at('//tapi/document/result/query').text.should == 'ミッドナイトクラブ'
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require File.expand_path('../../spec_helper', File.dirname(__FILE__))
5
+ require 'web_service/simple/response'
6
+ require 'web_service/simple/parser'
7
+ require 'web_service/simple/parser/json'
8
+
9
+ describe WebService::Simple::Response do
10
+ before do
11
+ @parser = WebService::Simple::Parser::JSON.new
12
+ @content = '{ error: 1 }'
13
+ @response = WebService::Simple::Response.new(@content, @parser)
14
+ end
15
+
16
+ describe 'を作成するとき' do
17
+ it 'は、第 1 引数を @content に、第 2 引数を @parser に設定すること' do
18
+ @response.content.should == @content
19
+ end
20
+ end
21
+
22
+ describe '#parse_response' do
23
+ it 'は、パーサの parse_response メソッドを、自身を引数として呼び出すこと' do
24
+ @parser.should_receive(:parse_response).with(@response)
25
+ @response.parse_response
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
5
+ require 'web_service/simple'
6
+ require 'tempfile'
7
+
8
+ describe WebService::Simple do
9
+ it { WebService::Simple::VERSION.should =~ /\A\d+\.\d+\.\d+\Z/ }
10
+
11
+ before do
12
+ @base_url = 'http://api.example.com'
13
+ @service = WebService::Simple.new(:base_url => @base_url)
14
+ end
15
+
16
+ describe 'を作成するとき' do
17
+ it 'は、:base_url の値を @base_url に設定すること' do
18
+ service = WebService::Simple.new(:base_url => @base_url)
19
+ service.base_url.should == @base_url
20
+ end
21
+
22
+ it 'で、:base_url の値が未指定ならば ArgumentError が発生すること' do
23
+ proc { WebService::Simple.new }.should raise_error(ArgumentError)
24
+ end
25
+
26
+ it 'は、:logger の値を @logger に設定すること' do
27
+ logger = Logger.new(STDOUT)
28
+ service = WebService::Simple.new(:base_url => @base_url, :logger => logger)
29
+ service.logger.should == logger
30
+ end
31
+
32
+ it 'は、:debug の値を @debug に設定すること' do
33
+ service = WebService::Simple.new(:base_url => @base_url, :debug => true)
34
+ service.debug.should be_true
35
+ end
36
+
37
+ it 'は、:params の値を @basic_params に設定すること' do
38
+ params = { :key => 'xxx' }
39
+ service = WebService::Simple.new(:base_url => @base_url, :params => params)
40
+ service.basic_params.should == params
41
+ end
42
+
43
+ it 'は、:param の値を @basic_params に設定すること' do
44
+ param = { :key => 'xxx' }
45
+ service = WebService::Simple.new(:base_url => @base_url, :param => param)
46
+ service.basic_params.should == param
47
+ end
48
+
49
+ it 'は、:response_parser の値を @response_parer に設定すること' do
50
+ service = WebService::Simple.new(:base_url => @base_url, :response_parser => 'XML::Nokogiri')
51
+ service.response_parser.should_not be_nil
52
+
53
+ service = WebService::Simple.new(:base_url => @base_url, :response_parser => { :module => 'XML::Nokogiri' })
54
+ service.response_parser.should_not be_nil
55
+
56
+ parser = WebService::Simple::Parser::XML::Nokogiri.new
57
+ service = WebService::Simple.new(:base_url => @base_url, :response_parser => parser)
58
+ service.response_parser.should_not be_nil
59
+ end
60
+
61
+ it 'で、:response_parser の値が未指定ならば @@config の値から @response_parser を設定すること' do
62
+ service = WebService::Simple.new(:base_url => @base_url)
63
+ service.response_parser.class.should == WebService::Simple::Parser::XML::Nokogiri
64
+ end
65
+ end
66
+
67
+ describe '#logger' do
68
+ it 'は、@logger を返すこと' do
69
+ logger = Logger.new(StringIO.new)
70
+ @service.logger = logger
71
+ @service.logger.should == logger
72
+ end
73
+
74
+ it 'は、@logger が nil ならば標準出力 INFO レベルの Logger を返すこと' do
75
+ logger = @service.logger
76
+ logger.class.should == Logger
77
+ logger.level.should == Logger::INFO
78
+ end
79
+ end
80
+
81
+ describe '#response_parser' do
82
+ it 'は、@response_parser が文字列ならば、そのレスポンスパーサを生成して返すこと' do
83
+ @service.response_parser = 'XML::Nokogiri'
84
+ @service.response_parser.class.should == WebService::Simple::Parser::XML::Nokogiri
85
+ end
86
+
87
+ it 'は、@response_parser がハッシュならば、そのレスポンスパーサを生成して返すこと' do
88
+ @service.response_parser = { :module => 'XML::Nokogiri' }
89
+ @service.response_parser.class.should == WebService::Simple::Parser::XML::Nokogiri
90
+ end
91
+
92
+ it 'は、@response_parser が Parser オブジェクトならば、それを返すこと' do
93
+ parser = WebService::Simple::Parser::XML::Nokogiri.new
94
+ @service.response_parser = parser
95
+ @service.response_parser.should == parser
96
+ end
97
+ end
98
+
99
+ describe '#get' do
100
+ before do
101
+ FakeWeb.clean_registry
102
+ FakeWeb.allow_net_connect = false
103
+ end
104
+
105
+ before do
106
+ @service = WebService::Simple.new(:base_url => 'http://api.example.com', :param => { :key => 'xxx' })
107
+ end
108
+
109
+ it 'は、GET リクエストを送信して、Response オブジェクトを返すこと' do
110
+ FakeWeb.register_uri(:get, 'http://api.example.com?key=xxx', :string => 'ok')
111
+
112
+ response = @service.get
113
+ response.class.should == WebService::Simple::Response
114
+ response.content.should == 'ok'
115
+ end
116
+
117
+ it 'は、リクエストの結果、レスポンスコードが 200 以外ならば、例外 ResponseCodeError が発生すること' do
118
+ FakeWeb.register_uri(:get, 'http://api.example.com?key=xxx', :string => 'nf', :status => ['404', 'Not Found'])
119
+ begin
120
+ @service.get
121
+ rescue => e
122
+ e.class.should == WebService::Simple::ResponseCodeError
123
+ e.response_code.should == '404'
124
+ e.response_body.should == 'nf'
125
+ end
126
+ end
127
+
128
+ it 'は、引数に応じて、よしなにリクエストすること' do
129
+ FakeWeb.register_uri(:get, 'http://api.example.com?key=xxx&word=yyy', :string => 'ok1')
130
+ FakeWeb.register_uri(:get, 'http://api.example.com/hage?key=xxx&word=yyy', :string => 'ok2')
131
+ FakeWeb.register_uri(:get, 'http://api.example.com/hage?key=xxx', :string => 'ok3')
132
+
133
+ @service.get(:word => 'yyy').content.should == 'ok1'
134
+ @service.get('/hage', :word => 'yyy').content.should == 'ok2'
135
+ @service.get('/hage').content.should == 'ok3'
136
+ @service.get('/hage').content.should == 'ok3'
137
+
138
+ service = WebService::Simple.new(:base_url => 'http://api.example.com/hage', :param => { :key => 'xxx' })
139
+ service.get.content.should == 'ok3'
140
+ end
141
+
142
+ it 'は、デバッグモードではないならば、ログを出力しないこと' do
143
+ io = StringIO.new
144
+ logger = Logger.new(io)
145
+ @service.logger = logger
146
+ @service.debug = false
147
+
148
+ io.string.should be_empty
149
+ end
150
+
151
+ describe 'で、デバッグモードのとき' do
152
+ before do
153
+ @io = StringIO.new
154
+ @logger = Logger.new(@io)
155
+
156
+ FakeWeb.register_uri(:get, @base_url, :string => 'ok')
157
+
158
+ @service = WebService::Simple.new(:base_url => @base_url, :debug => true)
159
+ end
160
+
161
+ it 'は、logger に対して INFO レベルのログを出力すること' do
162
+ @logger.level = Logger::INFO
163
+ @service.logger = @logger
164
+ @service.get
165
+
166
+ @io.string.should =~ %r!#{ Regexp.escape(@base_url) }!
167
+ end
168
+
169
+ it 'は、logger が INFO より上のレベルに設定されていればログを出力しないこと' do
170
+ @logger.level = Logger::WARN
171
+ @service.logger = @logger
172
+ @service.get
173
+
174
+ @io.string.should be_empty
175
+ end
176
+ end
177
+ end
178
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: milk1000cc-web_service_simple
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - milk1000cc
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-19 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Simple Interface To Web Services APIs (Ruby)
17
+ email: info@milk1000.cc
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.textile
26
+ - init.rb
27
+ - lib/web_service/simple.rb
28
+ - lib/web_service/simple/parser.rb
29
+ - lib/web_service/simple/parser/json.rb
30
+ - lib/web_service/simple/parser/xml/nokogiri.rb
31
+ - lib/web_service/simple/response.rb
32
+ - lib/web_service/simple/response_code_error.rb
33
+ - lib/web_service_simple.rb
34
+ - spec/spec_helper.rb
35
+ - spec/web_service/simple/parser/json_spec.rb
36
+ - spec/web_service/simple/parser/xml/nokogiri_spec.rb
37
+ - spec/web_service/simple/response_spec.rb
38
+ - spec/web_service/simple_spec.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/milk1000cc/web_service_simple/tree/master
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.2.0
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: Simple Interface To Web Services APIs (Ruby)
65
+ test_files: []
66
+