httparty 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of httparty might be problematic. Click here for more details.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +29 -0
- data/PostInstall.txt +1 -0
- data/README.txt +51 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +73 -0
- data/config/requirements.rb +15 -0
- data/examples/aaws.rb +30 -0
- data/examples/delicious.rb +40 -0
- data/examples/twitter.rb +36 -0
- data/examples/whoismyrep.rb +10 -0
- data/httparty.gemspec +33 -0
- data/lib/httparty.rb +135 -0
- data/lib/httparty/core_ext.rb +2 -0
- data/lib/httparty/core_ext/hash.rb +21 -0
- data/lib/httparty/version.rb +9 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/spec/hash_spec.rb +11 -0
- data/spec/httparty_spec.rb +145 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- metadata +96 -0
data/History.txt
ADDED
data/License.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 John Nunemaker
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
History.txt
|
2
|
+
License.txt
|
3
|
+
Manifest.txt
|
4
|
+
PostInstall.txt
|
5
|
+
README.txt
|
6
|
+
Rakefile
|
7
|
+
config/hoe.rb
|
8
|
+
config/requirements.rb
|
9
|
+
examples/aaws.rb
|
10
|
+
examples/delicious.rb
|
11
|
+
examples/twitter.rb
|
12
|
+
examples/whoismyrep.rb
|
13
|
+
httparty.gemspec
|
14
|
+
lib/httparty.rb
|
15
|
+
lib/httparty/core_ext.rb
|
16
|
+
lib/httparty/core_ext/hash.rb
|
17
|
+
lib/httparty/version.rb
|
18
|
+
script/console
|
19
|
+
script/destroy
|
20
|
+
script/generate
|
21
|
+
script/txt2html
|
22
|
+
setup.rb
|
23
|
+
spec/hash_spec.rb
|
24
|
+
spec/httparty_spec.rb
|
25
|
+
spec/spec.opts
|
26
|
+
spec/spec_helper.rb
|
27
|
+
tasks/deployment.rake
|
28
|
+
tasks/environment.rake
|
29
|
+
tasks/website.rake
|
data/PostInstall.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
When you HTTParty, you must party hard!
|
data/README.txt
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
= httparty
|
2
|
+
|
3
|
+
== DESCRIPTION:
|
4
|
+
|
5
|
+
Makes http fun again!
|
6
|
+
|
7
|
+
== FEATURES/PROBLEMS:
|
8
|
+
|
9
|
+
* Easy get, post, put, delete requests
|
10
|
+
* Basic http authentication
|
11
|
+
* Default request query string parameters (ie: for api keys that are needed on each request)
|
12
|
+
* Automatic parsing of JSON and XML into ruby hashes
|
13
|
+
|
14
|
+
== SYNOPSIS:
|
15
|
+
|
16
|
+
The following is a simple example of wrapping Twitter's API for posting updates.
|
17
|
+
|
18
|
+
class Twitter
|
19
|
+
include HTTParty
|
20
|
+
base_uri 'twitter.com'
|
21
|
+
basic_auth 'username', 'password'
|
22
|
+
end
|
23
|
+
|
24
|
+
Twitter.post('/statuses/update.json', :query => {:status => "It's an HTTParty and everyone is invited!"})
|
25
|
+
|
26
|
+
That is really it! The object returned is a ruby hash that is decoded from Twitter's json response. JSON parsing is used because of the .json extension in the path of the request. You can also explicitly set a format (see the examples).
|
27
|
+
|
28
|
+
That works and all but what if you don't want to embed your username and password in the class? Below is an example to fix that:
|
29
|
+
|
30
|
+
class Twitter
|
31
|
+
include HTTParty
|
32
|
+
base_uri 'twitter.com'
|
33
|
+
|
34
|
+
def initialize(user, pass)
|
35
|
+
self.class.basic_auth user, pass
|
36
|
+
end
|
37
|
+
|
38
|
+
def post(text)
|
39
|
+
self.class.post('/statuses/update.json', :query => {:status => text})
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Twitter.new('username', 'password').post("It's an HTTParty and everyone is invited!")
|
44
|
+
|
45
|
+
== REQUIREMENTS:
|
46
|
+
|
47
|
+
* Active Support >= 2.1
|
48
|
+
|
49
|
+
== INSTALL:
|
50
|
+
|
51
|
+
* sudo gem install httparty
|
data/Rakefile
ADDED
data/config/hoe.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'httparty/version'
|
2
|
+
|
3
|
+
AUTHOR = 'John Nunemaker' # can also be an array of Authors
|
4
|
+
EMAIL = "nunemaker@gmail.com"
|
5
|
+
DESCRIPTION = "Makes http fun! Also, makes consuming restful web services dead easy."
|
6
|
+
GEM_NAME = 'httparty' # what ppl will type to install your gem
|
7
|
+
RUBYFORGE_PROJECT = 'httparty' # The unix name for your project
|
8
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
9
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
10
|
+
EXTRA_DEPENDENCIES = [
|
11
|
+
['activesupport', '>= 2.1']
|
12
|
+
] # An array of rubygem dependencies [name, version]
|
13
|
+
|
14
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
15
|
+
@config = nil
|
16
|
+
RUBYFORGE_USERNAME = "unknown"
|
17
|
+
def rubyforge_username
|
18
|
+
unless @config
|
19
|
+
begin
|
20
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
21
|
+
rescue
|
22
|
+
puts <<-EOS
|
23
|
+
ERROR: No rubyforge config file found: #{@config_file}
|
24
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
25
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
26
|
+
EOS
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end
|
30
|
+
RUBYFORGE_USERNAME.replace @config["username"]
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
REV = nil
|
35
|
+
# UNCOMMENT IF REQUIRED:
|
36
|
+
# REV = YAML.load(`svn info`)['Revision']
|
37
|
+
VERS = HTTParty::VERSION::STRING + (REV ? ".#{REV}" : "")
|
38
|
+
RDOC_OPTS = ['--quiet', '--title', 'httparty documentation',
|
39
|
+
"--opname", "index.html",
|
40
|
+
"--line-numbers",
|
41
|
+
"--main", "README",
|
42
|
+
"--inline-source"]
|
43
|
+
|
44
|
+
class Hoe
|
45
|
+
def extra_deps
|
46
|
+
@extra_deps.reject! { |x| Array(x).first == 'hoe' }
|
47
|
+
@extra_deps
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Generate all the Rake tasks
|
52
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
53
|
+
$hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
54
|
+
p.developer(AUTHOR, EMAIL)
|
55
|
+
p.description = DESCRIPTION
|
56
|
+
p.summary = DESCRIPTION
|
57
|
+
p.url = HOMEPATH
|
58
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
59
|
+
p.test_globs = ["test/**/test_*.rb"]
|
60
|
+
p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
|
61
|
+
|
62
|
+
# == Optional
|
63
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
64
|
+
p.extra_deps = EXTRA_DEPENDENCIES
|
65
|
+
|
66
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
67
|
+
end
|
68
|
+
|
69
|
+
CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
|
70
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
71
|
+
$hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
72
|
+
$hoe.rsync_args = '-av --delete --ignore-errors'
|
73
|
+
$hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
%w[rake hoe newgem rubigen].each do |req_gem|
|
6
|
+
begin
|
7
|
+
require req_gem
|
8
|
+
rescue LoadError
|
9
|
+
puts "This Rakefile requires the '#{req_gem}' RubyGem."
|
10
|
+
puts "Installation: gem install #{req_gem} -y"
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
$:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
|
data/examples/aaws.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require File.join(dir, 'httparty')
|
3
|
+
require 'pp'
|
4
|
+
config = YAML::load(File.read(File.join(ENV['HOME'], '.aaws')))
|
5
|
+
|
6
|
+
module AAWS
|
7
|
+
class Book
|
8
|
+
include HTTParty
|
9
|
+
base_uri 'http://ecs.amazonaws.com'
|
10
|
+
default_params :Service => 'AWSECommerceService', :Operation => 'ItemSearch', :SearchIndex => 'Books'
|
11
|
+
format :xml
|
12
|
+
|
13
|
+
def initialize(key)
|
14
|
+
self.class.default_params :AWSAccessKeyId => key
|
15
|
+
end
|
16
|
+
|
17
|
+
def search(options={})
|
18
|
+
raise ArgumentError, 'You must search for something' if options[:query].blank?
|
19
|
+
|
20
|
+
# amazon uses nasty camelized query params
|
21
|
+
options[:query] = options[:query].inject({}) { |h, q| h[q[0].to_s.camelize] = q[1]; h }
|
22
|
+
|
23
|
+
# make a request and return the items (NOTE: this doesn't handle errors at this point)
|
24
|
+
self.class.get('/onca/xml', options)['ItemSearchResponse']['Items']
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
aaws = AAWS::Book.new(config[:access_key])
|
30
|
+
pp aaws.search(:query => {:title => 'Ruby On Rails'})
|
@@ -0,0 +1,40 @@
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require File.join(dir, 'httparty')
|
3
|
+
require 'pp'
|
4
|
+
config = YAML::load(File.read(File.join(ENV['HOME'], '.delicious')))
|
5
|
+
|
6
|
+
class Delicious
|
7
|
+
include HTTParty
|
8
|
+
base_uri 'https://api.del.icio.us/v1'
|
9
|
+
format :xml
|
10
|
+
|
11
|
+
def initialize(user, pass)
|
12
|
+
self.class.basic_auth(user, pass)
|
13
|
+
end
|
14
|
+
|
15
|
+
# query params that filter the posts are:
|
16
|
+
# tag (optional). Filter by this tag.
|
17
|
+
# dt (optional). Filter by this date (CCYY-MM-DDThh:mm:ssZ).
|
18
|
+
# url (optional). Filter by this url.
|
19
|
+
# ie: posts(:query => {:tag => 'ruby'})
|
20
|
+
def posts(options={})
|
21
|
+
# get posts and convert to structs so we can do .key instead of ['key'] with results
|
22
|
+
self.class.get('/posts/get', options)['posts']['post'].map { |b| b.to_struct }
|
23
|
+
end
|
24
|
+
|
25
|
+
# query params that filter the posts are:
|
26
|
+
# tag (optional). Filter by this tag.
|
27
|
+
# count (optional). Number of items to retrieve (Default:15, Maximum:100).
|
28
|
+
def recent(options={})
|
29
|
+
self.class.get('/posts/recent', options)['posts']['post'].map { |b| b.to_struct }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
delicious = Delicious.new(config['username'], config['password'])
|
34
|
+
|
35
|
+
pp delicious.posts(:query => {:tag => 'ruby'})
|
36
|
+
|
37
|
+
puts '', '*' * 50, ''
|
38
|
+
|
39
|
+
pp delicious.recent
|
40
|
+
|
data/examples/twitter.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require File.join(dir, 'httparty')
|
3
|
+
require 'pp'
|
4
|
+
config = YAML::load(File.read(File.join(ENV['HOME'], '.twitter')))
|
5
|
+
|
6
|
+
class Twitter
|
7
|
+
include HTTParty
|
8
|
+
base_uri 'twitter.com'
|
9
|
+
|
10
|
+
def initialize(user, pass)
|
11
|
+
self.class.basic_auth user, pass
|
12
|
+
end
|
13
|
+
|
14
|
+
# which can be :friends, :user or :public
|
15
|
+
# options[:query] can be things like since, since_id, count, etc.
|
16
|
+
def timeline(which=:friends, options={})
|
17
|
+
self.class.get("/statuses/#{which}_timeline.xml", options)['statuses'].map { |s| s.to_struct }
|
18
|
+
end
|
19
|
+
|
20
|
+
def post(text)
|
21
|
+
self.class.post('/statuses/update.xml', :query => {:status => text})['status'].to_struct
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
twitter = Twitter.new(config['email'], config['password'])
|
27
|
+
|
28
|
+
twitter.timeline.each do |s|
|
29
|
+
puts s.user.name, s.text, "#{s.created_at} #{s.id}", ''
|
30
|
+
end
|
31
|
+
|
32
|
+
# twitter.timeline(:friends, :query => {:since_id => 868482746}).each do |s|
|
33
|
+
# puts s.user.name, s.text, "#{s.created_at} #{s.id}", ''
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# pp twitter.post('this is a test')
|
@@ -0,0 +1,10 @@
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require File.join(dir, 'httparty')
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
class Rep
|
6
|
+
include HTTParty
|
7
|
+
format :xml
|
8
|
+
end
|
9
|
+
|
10
|
+
puts Rep.get('http://whoismyrepresentative.com/whoismyrep.php?zip=46544').inspect
|
data/httparty.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{httparty}
|
3
|
+
s.version = "0.1.0"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["John Nunemaker"]
|
7
|
+
s.date = %q{2008-07-28}
|
8
|
+
s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
9
|
+
s.email = ["nunemaker@gmail.com"]
|
10
|
+
s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "PostInstall.txt", "README.txt"]
|
11
|
+
s.files = ["History.txt", "License.txt", "Manifest.txt", "PostInstall.txt", "README.txt", "Rakefile", "config/hoe.rb", "config/requirements.rb", "examples/aaws.rb", "examples/delicious.rb", "examples/twitter.rb", "examples/whoismyrep.rb", "httparty.gemspec", "lib/httparty.rb", "lib/httparty/core_ext.rb", "lib/httparty/core_ext/hash.rb", "lib/httparty/version.rb", "script/console", "script/destroy", "script/generate", "script/txt2html", "setup.rb", "spec/hash_spec.rb", "spec/httparty_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/deployment.rake", "tasks/environment.rake", "tasks/website.rake"]
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.homepage = %q{http://httparty.rubyforge.org}
|
14
|
+
s.post_install_message = %q{When you HTTParty, you must party hard!}
|
15
|
+
s.rdoc_options = ["--main", "README.txt"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{httparty}
|
18
|
+
s.rubygems_version = %q{1.2.0}
|
19
|
+
s.summary = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 2
|
24
|
+
|
25
|
+
if current_version >= 3 then
|
26
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.1"])
|
27
|
+
else
|
28
|
+
s.add_dependency(%q<activesupport>, [">= 2.1"])
|
29
|
+
end
|
30
|
+
else
|
31
|
+
s.add_dependency(%q<activesupport>, [">= 2.1"])
|
32
|
+
end
|
33
|
+
end
|
data/lib/httparty.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'uri'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'active_support'
|
7
|
+
|
8
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
9
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
10
|
+
|
11
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), 'httparty'))
|
12
|
+
require dir + '/core_ext'
|
13
|
+
|
14
|
+
module HTTParty
|
15
|
+
def self.included(base)
|
16
|
+
base.extend ClassMethods
|
17
|
+
end
|
18
|
+
|
19
|
+
class UnsupportedFormat < StandardError; end
|
20
|
+
|
21
|
+
AllowedFormats = %w[xml json]
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def base_uri(base_uri=nil)
|
25
|
+
return @base_uri unless base_uri
|
26
|
+
# don't want this to ever end with /
|
27
|
+
base_uri = base_uri.ends_with?('/') ? base_uri.chop : base_uri
|
28
|
+
@base_uri = normalize_base_uri(base_uri)
|
29
|
+
end
|
30
|
+
|
31
|
+
def basic_auth(u, p)
|
32
|
+
@auth = {:username => u, :password => p}
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_params(h={})
|
36
|
+
raise ArgumentError, 'Default params must be a hash' unless h.is_a?(Hash)
|
37
|
+
@default_params ||= {}
|
38
|
+
return @default_params if h.blank?
|
39
|
+
@default_params.merge!(h)
|
40
|
+
end
|
41
|
+
|
42
|
+
def headers(h={})
|
43
|
+
raise ArgumentError, 'Headers must be a hash' unless h.is_a?(Hash)
|
44
|
+
@headers ||= {}
|
45
|
+
return @headers if h.blank?
|
46
|
+
@headers.merge!(h)
|
47
|
+
end
|
48
|
+
|
49
|
+
def format(f)
|
50
|
+
f = f.to_s
|
51
|
+
raise UnsupportedFormat, "Must be one of: #{AllowedFormats.join(', ')}" unless AllowedFormats.include?(f)
|
52
|
+
@format = f
|
53
|
+
end
|
54
|
+
|
55
|
+
# TODO: spec out this
|
56
|
+
def get(path, options={})
|
57
|
+
send_request 'get', path, options
|
58
|
+
end
|
59
|
+
|
60
|
+
# TODO: spec out this
|
61
|
+
def post(path, options={})
|
62
|
+
send_request 'post', path, options
|
63
|
+
end
|
64
|
+
|
65
|
+
# TODO: spec out this
|
66
|
+
def put(path, options={})
|
67
|
+
send_request 'put', path, options
|
68
|
+
end
|
69
|
+
|
70
|
+
# TODO: spec out this
|
71
|
+
def delete(path, options={})
|
72
|
+
send_request 'delete', path, options
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def http(uri)
|
77
|
+
if @http.blank?
|
78
|
+
@http = Net::HTTP.new(uri.host, uri.port)
|
79
|
+
@http.use_ssl = (uri.port == 443)
|
80
|
+
# so we can avoid ssl warnings
|
81
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
82
|
+
end
|
83
|
+
@http
|
84
|
+
end
|
85
|
+
|
86
|
+
# options can be any or all of:
|
87
|
+
# query => hash of keys/values to be converted to query string
|
88
|
+
# body => string for raw post data
|
89
|
+
# headers => hash of headers to send request with
|
90
|
+
def send_request(method, path, options={})
|
91
|
+
raise ArgumentError, 'only get, post, put and delete methods are supported' unless %w[get post put delete].include?(method.to_s)
|
92
|
+
raise ArgumentError, ':query must be a hash' if options[:query] && !options[:query].is_a?(Hash)
|
93
|
+
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
|
94
|
+
# we always want path that begins with /
|
95
|
+
path = path =~ /^(\/|https?:\/\/)/ ? path : "/#{path}"
|
96
|
+
@format ||= format_from_path(path)
|
97
|
+
uri = URI.parse("#{base_uri}#{path}")
|
98
|
+
current_qs = uri.query ? "#{uri.query}&" : ''
|
99
|
+
uri.query = current_qs + default_params.merge(options[:query] || {}).to_query
|
100
|
+
klass = Net::HTTP.const_get method.to_s.downcase.capitalize
|
101
|
+
request = klass.new(uri.request_uri)
|
102
|
+
request.body = options[:body] unless options[:body].blank?
|
103
|
+
request.initialize_http_header headers.merge(options[:headers] || {})
|
104
|
+
request.basic_auth(@auth[:username], @auth[:password]) if @auth
|
105
|
+
response = http(uri).start() { |conn| conn.request(request) }
|
106
|
+
parse_response(response.body)
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_response(body)
|
110
|
+
case @format
|
111
|
+
when 'xml'
|
112
|
+
Hash.from_xml(body)
|
113
|
+
when 'json'
|
114
|
+
ActiveSupport::JSON.decode(body)
|
115
|
+
else
|
116
|
+
# just return the response if no format
|
117
|
+
body
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Makes it so uri is sure to parse stuff like google.com with the http
|
122
|
+
def normalize_base_uri(str)
|
123
|
+
str =~ /^https?:\/\// ? str : "http#{'s' if str.include?(':443')}://#{str}"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Returns a format that we can handle from the path if possible.
|
127
|
+
# Just does simple pattern matching on file extention:
|
128
|
+
# /foobar.xml => 'xml'
|
129
|
+
# /foobar.json => 'json'
|
130
|
+
def format_from_path(path)
|
131
|
+
ext = File.extname(path)[1..-1]
|
132
|
+
!ext.blank? && AllowedFormats.include?(ext) ? ext : nil
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|