rs-httpclient 3.0.0.beta1

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.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +85 -0
  3. data/bin/httpclient +77 -0
  4. data/bin/jsonclient +85 -0
  5. data/lib/hexdump.rb +50 -0
  6. data/lib/http-access2/cookie.rb +1 -0
  7. data/lib/http-access2/http.rb +1 -0
  8. data/lib/http-access2.rb +55 -0
  9. data/lib/httpclient/auth.rb +924 -0
  10. data/lib/httpclient/cacert.pem +3252 -0
  11. data/lib/httpclient/cacert1024.pem +3866 -0
  12. data/lib/httpclient/connection.rb +88 -0
  13. data/lib/httpclient/cookie.rb +220 -0
  14. data/lib/httpclient/http.rb +1082 -0
  15. data/lib/httpclient/include_client.rb +85 -0
  16. data/lib/httpclient/jruby_ssl_socket.rb +594 -0
  17. data/lib/httpclient/session.rb +960 -0
  18. data/lib/httpclient/ssl_config.rb +452 -0
  19. data/lib/httpclient/ssl_socket.rb +150 -0
  20. data/lib/httpclient/timeout.rb +140 -0
  21. data/lib/httpclient/util.rb +222 -0
  22. data/lib/httpclient/version.rb +3 -0
  23. data/lib/httpclient/webagent-cookie.rb +459 -0
  24. data/lib/httpclient.rb +1331 -0
  25. data/lib/jsonclient.rb +66 -0
  26. data/lib/oauthclient.rb +111 -0
  27. data/sample/async.rb +8 -0
  28. data/sample/auth.rb +11 -0
  29. data/sample/cookie.rb +18 -0
  30. data/sample/dav.rb +103 -0
  31. data/sample/generate_test_keys.rb +99 -0
  32. data/sample/howto.rb +49 -0
  33. data/sample/jsonclient.rb +67 -0
  34. data/sample/oauth_buzz.rb +57 -0
  35. data/sample/oauth_friendfeed.rb +59 -0
  36. data/sample/oauth_twitter.rb +61 -0
  37. data/sample/ssl/0cert.pem +22 -0
  38. data/sample/ssl/0key.pem +30 -0
  39. data/sample/ssl/1000cert.pem +19 -0
  40. data/sample/ssl/1000key.pem +18 -0
  41. data/sample/ssl/htdocs/index.html +10 -0
  42. data/sample/ssl/ssl_client.rb +22 -0
  43. data/sample/ssl/webrick_httpsd.rb +29 -0
  44. data/sample/stream.rb +21 -0
  45. data/sample/thread.rb +27 -0
  46. data/sample/wcat.rb +21 -0
  47. data/test/ca-chain.pem +40 -0
  48. data/test/ca.cert +20 -0
  49. data/test/ca.key +27 -0
  50. data/test/ca.srl +1 -0
  51. data/test/client-pass.key +30 -0
  52. data/test/client.cert +20 -0
  53. data/test/client.key +27 -0
  54. data/test/fixtures/verify.alt.cert +20 -0
  55. data/test/fixtures/verify.foo.cert +20 -0
  56. data/test/fixtures/verify.key +27 -0
  57. data/test/fixtures/verify.localhost.cert +20 -0
  58. data/test/helper.rb +129 -0
  59. data/test/htdigest +1 -0
  60. data/test/htpasswd +2 -0
  61. data/test/jruby_ssl_socket/test_pemutils.rb +32 -0
  62. data/test/runner.rb +2 -0
  63. data/test/server.cert +20 -0
  64. data/test/server.key +27 -0
  65. data/test/sslsvr.rb +65 -0
  66. data/test/subca.cert +20 -0
  67. data/test/subca.key +27 -0
  68. data/test/subca.srl +1 -0
  69. data/test/test_auth.rb +496 -0
  70. data/test/test_cookie.rb +309 -0
  71. data/test/test_hexdump.rb +13 -0
  72. data/test/test_http-access2.rb +516 -0
  73. data/test/test_httpclient.rb +2144 -0
  74. data/test/test_include_client.rb +52 -0
  75. data/test/test_jsonclient.rb +98 -0
  76. data/test/test_ssl.rb +522 -0
  77. data/test/test_webagent-cookie.rb +465 -0
  78. metadata +130 -0
data/lib/jsonclient.rb ADDED
@@ -0,0 +1,66 @@
1
+ require 'httpclient'
2
+ require 'json'
3
+
4
+ # JSONClient auto-converts Hash <-> JSON in request and response.
5
+ # * For PATCH, POST or PUT request, convert Hash body to JSON String with 'application/json; charset=utf-8' header.
6
+ # * For response, convert JSON String to Hash when content-type is '(application|text)/(x-)?json'
7
+ class JSONClient < HTTPClient
8
+ CONTENT_TYPE_JSON_REGEX = /(application|text)\/(x-)?json/i
9
+ CONTENT_TYPE_JSON = 'application/json; charset=utf-8'
10
+
11
+ attr_reader :content_type_json_request
12
+ attr_reader :content_type_json_response_regex
13
+
14
+ def initialize(*args)
15
+ super
16
+ @content_type_json_request = CONTENT_TYPE_JSON
17
+ @content_type_json_response_regex = CONTENT_TYPE_JSON_REGEX
18
+ end
19
+
20
+ def patch(uri, *args, &block)
21
+ request(:patch, uri, argument_to_hash_for_json(args), &block)
22
+ end
23
+
24
+ def post(uri, *args, &block)
25
+ request(:post, uri, argument_to_hash_for_json(args), &block)
26
+ end
27
+
28
+ def put(uri, *args, &block)
29
+ request(:put, uri, argument_to_hash_for_json(args), &block)
30
+ end
31
+
32
+ def request(method, uri, *args, &block)
33
+ res = super
34
+ if @content_type_json_response_regex =~ res.content_type
35
+ res = wrap_json_response(res)
36
+ end
37
+ res
38
+ end
39
+
40
+ private
41
+
42
+ def argument_to_hash_for_json(args)
43
+ hash = argument_to_hash(args, :body, :header, :follow_redirect)
44
+ if hash[:body].is_a?(Hash) || hash[:body].is_a?(Array)
45
+ hash[:header] = json_header(hash[:header])
46
+ hash[:body] = JSON.generate(hash[:body])
47
+ end
48
+ hash
49
+ end
50
+
51
+ def json_header(header)
52
+ header ||= {}
53
+ if header.is_a?(Hash)
54
+ header.merge('Content-Type' => @content_type_json_request)
55
+ else
56
+ header + [['Content-Type', @content_type_json_request]]
57
+ end
58
+ end
59
+
60
+ def wrap_json_response(original)
61
+ res = ::HTTP::Message.new_response(JSON.parse(original.content))
62
+ res.http_header = original.http_header
63
+ res.previous = original
64
+ res
65
+ end
66
+ end
@@ -0,0 +1,111 @@
1
+ # HTTPClient - HTTP client library.
2
+ # Copyright (C) 2000-2015 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
3
+ #
4
+ # This program is copyrighted free software by NAKAMURA, Hiroshi. You can
5
+ # redistribute it and/or modify it under the same terms of Ruby's license;
6
+ # either the dual license version in 2003, or any later version.
7
+
8
+
9
+ require 'httpclient'
10
+
11
+ module HTTP
12
+ class Message
13
+ attr_accessor :oauth_params
14
+ end
15
+ end
16
+
17
+
18
+ # OAuthClient provides OAuth related methods in addition to HTTPClient.
19
+ #
20
+ # See sample/ dir how to use OAuthClient. There are sample clients for Twitter,
21
+ # FriendFeed and Google Buzz.
22
+ class OAuthClient < HTTPClient
23
+
24
+ # HTTPClient::OAuth::Config:: OAuth configurator.
25
+ attr_accessor :oauth_config
26
+
27
+ # Creates a OAuthClient instance which provides OAuth related methods in
28
+ # addition to HTTPClient.
29
+ #
30
+ # Method signature is as same as HTTPClient. See HTTPClient.new
31
+ def initialize(*arg)
32
+ super
33
+ @oauth_config = HTTPClient::OAuth::Config.new
34
+ self.www_auth.oauth.set_config(nil, @oauth_config)
35
+ self.www_auth.oauth.challenge(nil)
36
+ self.strict_response_size_check = true
37
+ end
38
+
39
+ # Get request token.
40
+ # uri:: URI for request token.
41
+ # callback:: callback String. This can be nil for OAuth 1.0a
42
+ # param:: Additional query parameter Hash.
43
+ #
44
+ # It returns a HTTP::Message instance as a response. When the request is made
45
+ # successfully, you can retrieve a pair of request token and secret like
46
+ # following;
47
+ # res = client.get_request_token(...)
48
+ # token = res.oauth_params['oauth_token']
49
+ # secret = res.oauth_params['oauth_token_secret']
50
+ def get_request_token(uri, callback = nil, param = nil)
51
+ oauth_config.token = nil
52
+ oauth_config.secret = nil
53
+ oauth_config.callback = callback
54
+ oauth_config.verifier = nil
55
+ res = request(oauth_config.http_method, uri, param)
56
+ filter_response(res)
57
+ res
58
+ end
59
+
60
+ # Get access token.
61
+ # uri:: URI for request token.
62
+ # request_token:: a request token String. See get_access_token.
63
+ # request_token_secret:: a request secret String. See get_access_token.
64
+ # verifier:: a verifier tag String.
65
+ #
66
+ # When the request succeeds and the server returns a pair of access token
67
+ # and secret, oauth_config.token and oauth_token.secret are updated with
68
+ # the access token. Then you can call OAuthClient#get, #post, #delete, etc.
69
+ # All requests are signed.
70
+ def get_access_token(uri, request_token, request_token_secret, verifier = nil)
71
+ oauth_config.token = request_token
72
+ oauth_config.secret = request_token_secret
73
+ oauth_config.callback = nil
74
+ oauth_config.verifier = verifier
75
+ res = request(oauth_config.http_method, uri)
76
+ filter_response(res)
77
+ oauth_config.verifier = nil
78
+ res
79
+ end
80
+
81
+ # Parse response and returns a Hash.
82
+ def get_oauth_response(res)
83
+ enc = res.header['content-encoding']
84
+ body = nil
85
+ if enc and enc[0] and enc[0].downcase == 'gzip'
86
+ body = Zlib::GzipReader.wrap(StringIO.new(res.content)) { |gz| gz.read }
87
+ else
88
+ body = res.content
89
+ end
90
+ body.split('&').inject({}) { |r, e|
91
+ key, value = e.split('=', 2)
92
+ r[unescape(key)] = unescape(value)
93
+ r
94
+ }
95
+ end
96
+
97
+ private
98
+
99
+ def unescape(escaped)
100
+ escaped ? ::HTTP::Message.unescape(escaped) : nil
101
+ end
102
+
103
+ def filter_response(res)
104
+ if res.status == 200
105
+ if res.oauth_params = get_oauth_response(res)
106
+ oauth_config.token = res.oauth_params['oauth_token']
107
+ oauth_config.secret = res.oauth_params['oauth_token_secret']
108
+ end
109
+ end
110
+ end
111
+ end
data/sample/async.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'httpclient'
2
+
3
+ c = HTTPClient.new
4
+ conn = c.get_async("http://dev.ctor.org/")
5
+ io = conn.pop.content
6
+ while str = io.read(40)
7
+ p str
8
+ end
data/sample/auth.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'httpclient'
2
+
3
+ c = HTTPClient.new
4
+ c.debug_dev = STDOUT
5
+
6
+ # for Proxy authentication: supports Basic, Negotiate and NTLM.
7
+ #c.set_proxy_auth("admin", "admin")
8
+
9
+ # for WWW authentication: supports Basic, Digest and Negotiate.
10
+ c.set_auth("http://dev.ctor.org/http-access2/", "username", "password")
11
+ p c.get("http://dev.ctor.org/http-access2/login")
data/sample/cookie.rb ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join('..', 'lib'))
4
+ require 'httpclient'
5
+
6
+ proxy = ENV['HTTP_PROXY']
7
+ clnt = HTTPClient.new(proxy)
8
+ clnt.set_cookie_store("cookie.dat")
9
+ clnt.debug_dev = STDOUT if $DEBUG
10
+
11
+ while urlstr = ARGV.shift
12
+ response = clnt.get(urlstr){ |data|
13
+ print data
14
+ }
15
+ p response.contenttype
16
+ end
17
+
18
+ clnt.save_cookie_store
data/sample/dav.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'uri'
2
+ require 'httpclient'
3
+
4
+ class DAV
5
+ attr_reader :headers
6
+
7
+ def initialize(uri = nil)
8
+ @uri = nil
9
+ @headers = {}
10
+ open(uri) if uri
11
+ proxy = ENV['HTTP_PROXY'] || ENV['http_proxy'] || nil
12
+ @client = HTTPClient.new(proxy)
13
+ end
14
+
15
+ def open(uri)
16
+ @uri = if uri.is_a?(URI)
17
+ uri
18
+ else
19
+ URI.parse(uri)
20
+ end
21
+ end
22
+
23
+ def set_basic_auth(user_id, passwd)
24
+ @client.set_basic_auth(@uri, user_id, passwd)
25
+ end
26
+
27
+ # TODO: propget/propset support
28
+
29
+ def propfind(target)
30
+ target_uri = @uri + target
31
+ res = @client.propfind(target_uri)
32
+ res.body.content
33
+ end
34
+
35
+ def get(target, local = nil)
36
+ local ||= target
37
+ target_uri = @uri + target
38
+ if FileTest.exist?(local)
39
+ raise RuntimeError.new("File #{ local } exists.")
40
+ end
41
+ f = File.open(local, "wb")
42
+ res = @client.get(target_uri, nil, @headers) do |data|
43
+ f << data
44
+ end
45
+ f.close
46
+ STDOUT.puts("#{ res.header['content-length'][0] } bytes saved to file #{ target }.")
47
+ end
48
+
49
+ def debug_dev=(dev)
50
+ @client.debug_dev = dev
51
+ end
52
+
53
+ def get_content(target)
54
+ target_uri = @uri + target
55
+ @client.get_content(target_uri, nil, @headers)
56
+ end
57
+
58
+ def put_content(target, content)
59
+ target_uri = @uri + target
60
+ res = @client.put(target_uri, content, @headers)
61
+ if res.status < 200 or res.status >= 300
62
+ raise "HTTP PUT failed: #{res.inspect}"
63
+ end
64
+ end
65
+
66
+ class Mock
67
+ attr_reader :headers
68
+
69
+ def initialize(uri = nil)
70
+ @uri = nil
71
+ @headers = {}
72
+ open(uri) if uri
73
+
74
+ @cache = {}
75
+ end
76
+
77
+ def open(uri)
78
+ @uri = uri.is_a?(URI) ? uri : URI.parse(uri)
79
+ end
80
+
81
+ def set_basic_auth(user_id, passwd)
82
+ # ignore
83
+ end
84
+
85
+ def propfind(target)
86
+ # not found
87
+ nil
88
+ end
89
+
90
+ def get(target, local = nil)
91
+ # ignore
92
+ end
93
+
94
+ def get_content(target)
95
+ @cache[target]
96
+ end
97
+
98
+ def put_content(target, content)
99
+ @cache[target] = content
100
+ nil
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,99 @@
1
+ require "openssl"
2
+
3
+ def build_ca
4
+ root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
5
+ root_ca = OpenSSL::X509::Certificate.new
6
+ root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
7
+ root_ca.serial = 1
8
+ root_ca.subject = OpenSSL::X509::Name.parse "C=JP,O=JIN.GR.JP,OU=RRR,CN=CA"
9
+ root_ca.issuer = root_ca.subject # root CA's are "self-signed"
10
+ root_ca.public_key = root_key.public_key
11
+ root_ca.not_before = Time.now
12
+ root_ca.not_after = root_ca.not_before + 10 * 365 * 24 * 60 * 60 # 10 years validity
13
+ ef = OpenSSL::X509::ExtensionFactory.new
14
+ ef.subject_certificate = root_ca
15
+ ef.issuer_certificate = root_ca
16
+ root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
17
+ root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
18
+ root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
19
+ root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
20
+ root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
21
+ [root_key, root_ca]
22
+ end
23
+
24
+ root_key, root_ca = build_ca
25
+
26
+ File.write("test/ca.cert", root_ca.to_s)
27
+ File.write("test/ca.key", root_key.to_s)
28
+
29
+ def sub_cert(root_key, root_ca, cn, intermediate: false)
30
+ key = OpenSSL::PKey::RSA.new 2048
31
+ cert = OpenSSL::X509::Certificate.new
32
+ cert.version = 2
33
+ cert.serial = 2
34
+ cert.subject = OpenSSL::X509::Name.parse "C=JP,O=JIN.GR.JP,OU=RRR,CN=#{cn}"
35
+ cert.issuer = root_ca.subject # root CA is the issuer
36
+ cert.public_key = key.public_key
37
+ cert.not_before = Time.now
38
+ cert.not_after = cert.not_before + 9 * 365 * 24 * 60 * 60 # 9 years validity
39
+ ef = OpenSSL::X509::ExtensionFactory.new
40
+ ef.subject_certificate = cert
41
+ ef.issuer_certificate = root_ca
42
+ cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
43
+ if intermediate
44
+ cert.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
45
+ cert.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
46
+ else
47
+ cert.add_extension(ef.create_extension("keyUsage","digitalSignature, keyEncipherment", true))
48
+ cert.add_extension(ef.create_extension("extendedKeyUsage", "serverAuth"))
49
+ end
50
+ cert.sign(root_key, OpenSSL::Digest::SHA256.new)
51
+ [key, cert]
52
+ end
53
+
54
+ sub_key, sub_cert = sub_cert(root_key, root_ca, "SubCA", intermediate: true)
55
+ File.write("test/subca.cert", sub_cert.to_s)
56
+ File.write("test/subca.key", sub_key.to_s)
57
+
58
+ server_key, server_cert = sub_cert(sub_key, sub_cert, "localhost")
59
+ File.write("test/server.cert", server_cert.to_s)
60
+ File.write("test/server.key", server_key.to_s)
61
+
62
+ client_key, client_cert = sub_cert(root_key, root_ca, "localhost")
63
+ File.write("test/client.cert", client_cert.to_s)
64
+ File.write("test/client.key", client_key.to_s)
65
+
66
+ system(
67
+ "openssl", "rsa", "-aes256",
68
+ "-in", "test/client.key",
69
+ "-out", "test/client-pass.key",
70
+ "-passout", "pass:pass4key",
71
+ )
72
+
73
+ File.write("test/ca-chain.pem", root_ca.to_s + sub_cert.to_s)
74
+
75
+ verify_key = OpenSSL::PKey::RSA.new 2048
76
+ File.write("test/fixtures/verify.key", verify_key.to_s)
77
+
78
+ def build_self_signed(key, cn)
79
+ cert = OpenSSL::X509::Certificate.new
80
+ cert.version = 2
81
+ cert.serial = 2
82
+ cert.subject = OpenSSL::X509::Name.parse "C=JP,O=JIN.GR.JP,OU=RRR,CN=#{cn}"
83
+ cert.issuer = cert.subject
84
+ cert.public_key = key.public_key
85
+ cert.not_before = Time.now
86
+ cert.not_after = cert.not_before + 9 * 365 * 24 * 60 * 60 # 9 years validity
87
+ ef = OpenSSL::X509::ExtensionFactory.new
88
+ ef.subject_certificate = cert
89
+ ef.issuer_certificate = cert
90
+ cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
91
+ cert.add_extension(ef.create_extension("keyUsage","digitalSignature, keyEncipherment", true))
92
+ cert.add_extension(ef.create_extension("extendedKeyUsage", "serverAuth"))
93
+ cert.sign(key, OpenSSL::Digest::SHA256.new)
94
+ cert
95
+ end
96
+
97
+ File.write("test/fixtures/verify.localhost.cert", build_self_signed(verify_key, "localhost").to_s)
98
+ File.write("test/fixtures/verify.foo.cert", build_self_signed(verify_key, "foo").to_s)
99
+ File.write("test/fixtures/verify.alt.cert", build_self_signed(verify_key, "alt").to_s)
data/sample/howto.rb ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join('..', 'lib'))
4
+ require 'httpclient'
5
+
6
+ proxy = ENV['HTTP_PROXY']
7
+ clnt = HTTPClient.new(proxy)
8
+ clnt.set_cookie_store("cookie.dat")
9
+ target = ARGV.shift || "http://localhost/foo.cgi"
10
+
11
+ puts
12
+ puts '= GET content directly'
13
+ puts clnt.get_content(target)
14
+
15
+ puts '= GET result object'
16
+ result = clnt.get(target)
17
+ puts '== Header object'
18
+ p result.header
19
+ puts "== Content-type"
20
+ p result.contenttype
21
+ puts '== Body object'
22
+ p result.body
23
+ puts '== Content'
24
+ print result.content
25
+ puts '== GET with Block'
26
+ clnt.get(target) do |str|
27
+ puts str
28
+ end
29
+
30
+ puts
31
+ puts '= GET with query'
32
+ puts clnt.get(target, { "foo" => "bar", "baz" => "quz" }).content
33
+
34
+ puts
35
+ puts '= GET with query 2'
36
+ puts clnt.get(target, [["foo", "bar1"], ["foo", "bar2"]]).content
37
+
38
+ clnt.debug_dev = STDERR
39
+ puts
40
+ puts '= GET with extra header'
41
+ puts clnt.get(target, nil, { "SOAPAction" => "HelloWorld" }).content
42
+
43
+ puts
44
+ puts '= GET with extra header 2'
45
+ puts clnt.get(target, nil, [["Accept", "text/plain"], ["Accept", "text/html"]]).content
46
+
47
+ clnt.debug_dev = nil
48
+
49
+ clnt.save_cookie_store
@@ -0,0 +1,67 @@
1
+ require 'httpclient'
2
+ require 'json'
3
+
4
+ module HTTP
5
+ class Message
6
+ # Returns JSON object of message body
7
+ alias original_content content
8
+ def content
9
+ if JSONClient::CONTENT_TYPE_JSON_REGEX =~ content_type
10
+ JSON.parse(original_content)
11
+ else
12
+ original_content
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+
19
+ # JSONClient provides JSON related methods in addition to HTTPClient.
20
+ class JSONClient < HTTPClient
21
+ CONTENT_TYPE_JSON_REGEX = /(application|text)\/(x-)?json/i
22
+
23
+ attr_accessor :content_type_json
24
+
25
+ class JSONRequestHeaderFilter
26
+ attr_accessor :replace
27
+
28
+ def initialize(client)
29
+ @client = client
30
+ @replace = false
31
+ end
32
+
33
+ def filter_request(req)
34
+ req.header['content-type'] = @client.content_type_json if @replace
35
+ end
36
+
37
+ def filter_response(req, res)
38
+ @replace = false
39
+ end
40
+ end
41
+
42
+ def initialize(*args)
43
+ super
44
+ @header_filter = JSONRequestHeaderFilter.new(self)
45
+ @request_filter << @header_filter
46
+ @content_type_json = 'application/json; charset=utf-8'
47
+ end
48
+
49
+ def post(uri, *args, &block)
50
+ @header_filter.replace = true
51
+ request(:post, uri, jsonify(argument_to_hash(args, :body, :header, :follow_redirect)), &block)
52
+ end
53
+
54
+ def put(uri, *args, &block)
55
+ @header_filter.replace = true
56
+ request(:put, uri, jsonify(argument_to_hash(args, :body, :header)), &block)
57
+ end
58
+
59
+ private
60
+
61
+ def jsonify(hash)
62
+ if hash[:body] && hash[:body].is_a?(Hash)
63
+ hash[:body] = JSON.generate(hash[:body])
64
+ end
65
+ hash
66
+ end
67
+ end
@@ -0,0 +1,57 @@
1
+ require 'oauthclient'
2
+ require 'zlib'
3
+ require 'stringio'
4
+
5
+ # Get your own consumer token from http://code.google.com/apis/accounts/docs/RegistrationForWebAppsAuto.html
6
+ consumer_key = nil
7
+ consumer_secret = nil
8
+
9
+ callback = 'http://localhost/' # should point somewhere else...
10
+ scope = 'https://www.googleapis.com/auth/buzz'
11
+ request_token_url = 'https://www.google.com/accounts/OAuthGetRequestToken'
12
+ access_token_url = 'https://www.google.com/accounts/OAuthGetAccessToken'
13
+
14
+ STDOUT.sync = true
15
+
16
+ # create OAuth client.
17
+ client = OAuthClient.new
18
+ client.oauth_config.consumer_key = consumer_key
19
+ client.oauth_config.consumer_secret = consumer_secret
20
+ client.oauth_config.signature_method = 'HMAC-SHA1'
21
+ client.oauth_config.http_method = :get # Twitter does not allow :post
22
+ client.debug_dev = STDERR if $DEBUG
23
+
24
+ # Get request token.
25
+ res = client.get_request_token(request_token_url, callback, :scope => scope)
26
+ p res.status
27
+ p res.oauth_params
28
+ p res.content
29
+ p client.oauth_config
30
+ token = res.oauth_params['oauth_token']
31
+ secret = res.oauth_params['oauth_token_secret']
32
+ raise if token.nil? or secret.nil?
33
+
34
+ # You need to confirm authorization out of band.
35
+ puts
36
+ puts "Go here and do confirm: https://www.google.com/buzz/api/auth/OAuthAuthorizeToken?oauth_token=#{token}&domain=#{consumer_key}&scope=#{scope}"
37
+ puts "Type oauth_verifier (if given) and hit [enter] to go"
38
+ require 'cgi'
39
+ verifier = CGI.unescape(gets.chomp)
40
+ verifier = nil if verifier.empty?
41
+
42
+ # Get access token.
43
+ res = client.get_access_token(access_token_url, token, secret, verifier)
44
+ p res.status
45
+ p res.oauth_params
46
+ p res.content
47
+ p client.oauth_config
48
+ id = res.oauth_params['user_id']
49
+
50
+ puts
51
+ puts "Access token usage example"
52
+ puts "Hit [enter] to go"
53
+ gets
54
+
55
+ # Access to a protected resource.
56
+ # @consumption requires Buzz API
57
+ puts client.get_content("https://www.googleapis.com/buzz/v1/activities/@me/@consumption", :alt => :json, :prettyprint => true)
@@ -0,0 +1,59 @@
1
+ require 'oauthclient'
2
+
3
+ # Get your own consumer token from http://friendfeed.com/api/applications
4
+ consumer_key = 'EDIT HERE'
5
+ consumer_secret = 'EDIT HERE'
6
+
7
+ request_token_url = 'https://friendfeed.com/account/oauth/request_token'
8
+ oob_authorize_url = 'https://friendfeed.com/account/oauth/authorize'
9
+ access_token_url = 'https://friendfeed.com/account/oauth/access_token'
10
+
11
+ STDOUT.sync = true
12
+
13
+ # create OAuth client.
14
+ client = OAuthClient.new
15
+ client.oauth_config.consumer_key = consumer_key
16
+ client.oauth_config.consumer_secret = consumer_secret
17
+ client.oauth_config.signature_method = 'HMAC-SHA1'
18
+ client.oauth_config.http_method = :get # FriendFeed does not allow :post
19
+ client.debug_dev = STDERR if $DEBUG
20
+
21
+ # Get request token.
22
+ res = client.get_request_token(request_token_url)
23
+ p res.status
24
+ p res.oauth_params
25
+ p res.content
26
+ p client.oauth_config
27
+ token = res.oauth_params['oauth_token']
28
+ secret = res.oauth_params['oauth_token_secret']
29
+ raise if token.nil? or secret.nil?
30
+
31
+ # You need to confirm authorization out of band.
32
+ puts
33
+ puts "Go here and do confirm: #{oob_authorize_url}?oauth_token=#{token}"
34
+ puts "Hit [enter] to go"
35
+ gets
36
+
37
+ # Get access token.
38
+ # FYI: You may need to re-construct OAuthClient instance here.
39
+ # In normal web app flow, getting access token and getting request token
40
+ # must be done in different HTTP requests.
41
+ # client = OAuthClient.new
42
+ # client.oauth_config.consumer_key = consumer_key
43
+ # client.oauth_config.consumer_secret = consumer_secret
44
+ # client.oauth_config.signature_method = 'HMAC-SHA1'
45
+ # client.oauth_config.http_method = :get # Twitter does not allow :post
46
+ res = client.get_access_token(access_token_url, token, secret)
47
+ p res.status
48
+ p res.oauth_params
49
+ p res.content
50
+ p client.oauth_config
51
+ username = res.oauth_params['username']
52
+
53
+ puts
54
+ puts "Access token usage example"
55
+ puts "Hit [enter] to go"
56
+ gets
57
+
58
+ # Access to a protected resource. (user profile)
59
+ puts client.get("http://friendfeed-api.com/v2/feedinfo/#{username}?format=json")