alexvollmer-httparty 0.1.5
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/History.txt +32 -0
- data/License.txt +20 -0
- data/Manifest.txt +31 -0
- data/PostInstall.txt +1 -0
- data/README.txt +66 -0
- data/Rakefile +11 -0
- data/config/hoe.rb +73 -0
- data/config/requirements.rb +15 -0
- data/examples/aaws.rb +29 -0
- data/examples/delicious.rb +37 -0
- data/examples/google.rb +16 -0
- data/examples/twitter.rb +31 -0
- data/examples/whoismyrep.rb +9 -0
- data/httparty.gemspec +38 -0
- data/lib/httparty/request.rb +104 -0
- data/lib/httparty/version.rb +9 -0
- data/lib/httparty.rb +107 -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/httparty/request_spec.rb +142 -0
- data/spec/httparty_spec.rb +149 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +9 -0
- data/tasks/deployment.rake +43 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/website/css/common.css +47 -0
- data/website/index.html +83 -0
- metadata +106 -0
data/History.txt
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
== 0.1.5 2008-11-14
|
|
2
|
+
* 2 major enhancements
|
|
3
|
+
* Refactored send request method out into its own object.
|
|
4
|
+
* Added :html format if you just want to do that.
|
|
5
|
+
|
|
6
|
+
== 0.1.4 2008-11-08
|
|
7
|
+
* 3 major enhancements:
|
|
8
|
+
* Removed some cruft
|
|
9
|
+
* Added ability to follow redirects automatically and turn that off (Alex Vollmer)
|
|
10
|
+
|
|
11
|
+
== 0.1.3 2008-08-22
|
|
12
|
+
|
|
13
|
+
* 3 major enhancements:
|
|
14
|
+
* Added http_proxy key for setting proxy server and port (francxk@gmail.com)
|
|
15
|
+
* Now raises exception when http error occurs (francxk@gmail.com)
|
|
16
|
+
* Changed auto format detection from file extension to response content type (Jay Pignata)
|
|
17
|
+
|
|
18
|
+
== 0.1.2 2008-08-09
|
|
19
|
+
|
|
20
|
+
* 1 major enhancement:
|
|
21
|
+
* default_params were not being appended to query string if option[:query] was blank
|
|
22
|
+
|
|
23
|
+
== 0.1.1 2008-07-30
|
|
24
|
+
|
|
25
|
+
* 2 major enhancement:
|
|
26
|
+
* Added :basic_auth key for options when making a request
|
|
27
|
+
* :query and :body both now work with query string or hash
|
|
28
|
+
|
|
29
|
+
== 0.1.0 2008-07-27
|
|
30
|
+
|
|
31
|
+
* 1 major enhancement:
|
|
32
|
+
* Initial release
|
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,31 @@
|
|
|
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/google.rb
|
|
12
|
+
examples/twitter.rb
|
|
13
|
+
examples/whoismyrep.rb
|
|
14
|
+
httparty.gemspec
|
|
15
|
+
lib/httparty.rb
|
|
16
|
+
lib/httparty/request.rb
|
|
17
|
+
lib/httparty/version.rb
|
|
18
|
+
script/console
|
|
19
|
+
script/destroy
|
|
20
|
+
script/generate
|
|
21
|
+
script/txt2html
|
|
22
|
+
setup.rb
|
|
23
|
+
spec/httparty/request_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
|
|
30
|
+
website/css/common.css
|
|
31
|
+
website/index.html
|
data/PostInstall.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
When you HTTParty, you must party hard!
|
data/README.txt
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
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 based on response content-type
|
|
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(u, p)
|
|
35
|
+
@auth = {:username => u, :password => p}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def post(text)
|
|
39
|
+
options = { :query => {:status => text}, :basic_auth => @auth }
|
|
40
|
+
self.class.post('/statuses/update.json', options)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
Twitter.new('username', 'password').post("It's an HTTParty and everyone is invited!")
|
|
45
|
+
|
|
46
|
+
=== REQUEST OPTIONS
|
|
47
|
+
|
|
48
|
+
Each of the HTTP method (get, post, put and delete) each take a hash of options.
|
|
49
|
+
The following keys can be specified in the options:
|
|
50
|
+
|
|
51
|
+
headers:: A <tt>Hash</tt> of header key/value pairs
|
|
52
|
+
query:: A <tt>Hash</tt> of query key/value pairs
|
|
53
|
+
body:: The body of the request. If it's a <tt>Hash</tt>, it is
|
|
54
|
+
converted into query-string format, otherwise it is sent
|
|
55
|
+
as-is.
|
|
56
|
+
basic_auth:: A <tt>Hash</tt> containing keys for <tt>:username</tt> and
|
|
57
|
+
<tt>:password</tt>.
|
|
58
|
+
no_follow:: Turns off automatic redirect following
|
|
59
|
+
|
|
60
|
+
== REQUIREMENTS:
|
|
61
|
+
|
|
62
|
+
* Active Support >= 2.1
|
|
63
|
+
|
|
64
|
+
== INSTALL:
|
|
65
|
+
|
|
66
|
+
* sudo gem install httparty
|
data/Rakefile
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'config/requirements'
|
|
2
|
+
require 'config/hoe' # setup Hoe + all gem configuration
|
|
3
|
+
require "spec/rake/spectask"
|
|
4
|
+
|
|
5
|
+
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
|
6
|
+
|
|
7
|
+
task :default => :spec
|
|
8
|
+
|
|
9
|
+
Spec::Rake::SpecTask.new do |t|
|
|
10
|
+
t.spec_files = FileList["spec/**/*_spec.rb"]
|
|
11
|
+
end
|
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,29 @@
|
|
|
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
|
+
|
|
12
|
+
def initialize(key)
|
|
13
|
+
self.class.default_params :AWSAccessKeyId => key
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def search(options={})
|
|
17
|
+
raise ArgumentError, 'You must search for something' if options[:query].blank?
|
|
18
|
+
|
|
19
|
+
# amazon uses nasty camelized query params
|
|
20
|
+
options[:query] = options[:query].inject({}) { |h, q| h[q[0].to_s.camelize] = q[1]; h }
|
|
21
|
+
|
|
22
|
+
# make a request and return the items (NOTE: this doesn't handle errors at this point)
|
|
23
|
+
self.class.get('/onca/xml', options)['ItemSearchResponse']['Items']
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
aaws = AAWS::Book.new(config[:access_key])
|
|
29
|
+
pp aaws.search(:query => {:title => 'Ruby On Rails'})
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
|
|
10
|
+
def initialize(u, p)
|
|
11
|
+
@auth = {:username => u, :password => p}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# query params that filter the posts are:
|
|
15
|
+
# tag (optional). Filter by this tag.
|
|
16
|
+
# dt (optional). Filter by this date (CCYY-MM-DDThh:mm:ssZ).
|
|
17
|
+
# url (optional). Filter by this url.
|
|
18
|
+
# ie: posts(:query => {:tag => 'ruby'})
|
|
19
|
+
def posts(options={})
|
|
20
|
+
options.merge!({:basic_auth => @auth})
|
|
21
|
+
# get posts and convert to structs so we can do .key instead of ['key'] with results
|
|
22
|
+
self.class.get('/posts/get', options)
|
|
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
|
+
options.merge!({:basic_auth => @auth})
|
|
30
|
+
self.class.get('/posts/recent', options)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
delicious = Delicious.new(config['username'], config['password'])
|
|
35
|
+
pp delicious.posts(:query => {:tag => 'ruby'})
|
|
36
|
+
pp delicious.recent
|
|
37
|
+
|
data/examples/google.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
|
+
require File.join(dir, 'httparty')
|
|
3
|
+
require 'pp'
|
|
4
|
+
|
|
5
|
+
class Google
|
|
6
|
+
include HTTParty
|
|
7
|
+
format :html
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# google.com redirects to www.google.com so this is live test for redirection
|
|
11
|
+
pp Google.get('http://google.com')
|
|
12
|
+
|
|
13
|
+
puts '', '*'*70, ''
|
|
14
|
+
|
|
15
|
+
# check that ssl is requesting right
|
|
16
|
+
pp Google.get('https://www.google.com')
|
data/examples/twitter.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
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(u, p)
|
|
11
|
+
@auth = {:username => u, :password => p}
|
|
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
|
+
options.merge!({:basic_auth => @auth})
|
|
18
|
+
self.class.get("/statuses/#{which}_timeline.json", options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def post(text)
|
|
22
|
+
options = { :query => {:status => text}, :basic_auth => @auth }
|
|
23
|
+
self.class.post('/statuses/update.json', options)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
twitter = Twitter.new(config['email'], config['password'])
|
|
28
|
+
pp twitter.timeline
|
|
29
|
+
# pp twitter.timeline(:friends, :query => {:since_id => 868482746})
|
|
30
|
+
# pp twitter.timeline(:friends, :query => 'since_id=868482746')
|
|
31
|
+
# pp twitter.post('this is a test')
|
data/httparty.gemspec
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = %q{httparty}
|
|
5
|
+
s.version = "0.1.5"
|
|
6
|
+
|
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
8
|
+
s.authors = ["John Nunemaker"]
|
|
9
|
+
s.date = %q{2008-11-14}
|
|
10
|
+
s.description = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
|
11
|
+
s.email = ["nunemaker@gmail.com"]
|
|
12
|
+
s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "PostInstall.txt", "README.txt"]
|
|
13
|
+
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/google.rb", "examples/twitter.rb", "examples/whoismyrep.rb", "httparty.gemspec", "lib/httparty.rb", "lib/httparty/request.rb", "lib/httparty/version.rb", "script/console", "script/destroy", "script/generate", "script/txt2html", "setup.rb", "spec/httparty/request_spec.rb", "spec/httparty_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/deployment.rake", "tasks/environment.rake", "tasks/website.rake", "website/css/common.css", "website/index.html"]
|
|
14
|
+
s.has_rdoc = true
|
|
15
|
+
s.homepage = %q{http://httparty.rubyforge.org}
|
|
16
|
+
s.post_install_message = %q{When you HTTParty, you must party hard!}
|
|
17
|
+
s.rdoc_options = ["--main", "README.txt"]
|
|
18
|
+
s.require_paths = ["lib"]
|
|
19
|
+
s.rubyforge_project = %q{httparty}
|
|
20
|
+
s.rubygems_version = %q{1.3.1}
|
|
21
|
+
s.summary = %q{Makes http fun! Also, makes consuming restful web services dead easy.}
|
|
22
|
+
|
|
23
|
+
if s.respond_to? :specification_version then
|
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
25
|
+
s.specification_version = 2
|
|
26
|
+
|
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
28
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.1"])
|
|
29
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
|
30
|
+
else
|
|
31
|
+
s.add_dependency(%q<activesupport>, [">= 2.1"])
|
|
32
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
|
33
|
+
end
|
|
34
|
+
else
|
|
35
|
+
s.add_dependency(%q<activesupport>, [">= 2.1"])
|
|
36
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
module HTTParty
|
|
2
|
+
class Request
|
|
3
|
+
SupportedHTTPMethods = [Net::HTTP::Get, Net::HTTP::Post, Net::HTTP::Put, Net::HTTP::Delete]
|
|
4
|
+
|
|
5
|
+
attr_accessor :http_method, :path, :options
|
|
6
|
+
|
|
7
|
+
def initialize(http_method, path, options={})
|
|
8
|
+
self.http_method = http_method
|
|
9
|
+
self.path = path
|
|
10
|
+
self.options = {
|
|
11
|
+
:limit => options.delete(:no_follow) ? 0 : 5,
|
|
12
|
+
:default_params => {},
|
|
13
|
+
}.merge(options.dup)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def path=(uri)
|
|
17
|
+
@path = URI.parse(uri)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def uri
|
|
21
|
+
uri = path.relative? ? URI.parse("#{options[:base_uri]}#{path}") : path
|
|
22
|
+
uri.query = query_string(uri)
|
|
23
|
+
uri
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def perform
|
|
27
|
+
validate!
|
|
28
|
+
handle_response!(get_response(uri))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
def http(uri) #:nodoc:
|
|
33
|
+
http = Net::HTTP.new(uri.host, uri.port, options[:http_proxyaddr], options[:http_proxyport])
|
|
34
|
+
http.use_ssl = (uri.port == 443)
|
|
35
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
36
|
+
http
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def get_response(uri) #:nodoc:
|
|
40
|
+
request = http_method.new(uri.request_uri)
|
|
41
|
+
request.body = options[:body].is_a?(Hash) ? options[:body].to_query : options[:body] unless options[:body].blank?
|
|
42
|
+
request.initialize_http_header options[:headers]
|
|
43
|
+
request.basic_auth(options[:basic_auth][:username], options[:basic_auth][:password]) if options[:basic_auth]
|
|
44
|
+
response = http(uri).request(request)
|
|
45
|
+
options[:format] ||= format_from_mimetype(response['content-type'])
|
|
46
|
+
response
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def query_string(uri) #:nodoc:
|
|
50
|
+
query_string_parts = []
|
|
51
|
+
query_string_parts << uri.query unless uri.query.blank?
|
|
52
|
+
|
|
53
|
+
if options[:query].is_a?(Hash)
|
|
54
|
+
query_string_parts << options[:default_params].merge(options[:query]).to_query
|
|
55
|
+
else
|
|
56
|
+
query_string_parts << options[:default_params].to_query unless options[:default_params].blank?
|
|
57
|
+
query_string_parts << options[:query] unless options[:query].blank?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
query_string_parts.size > 0 ? query_string_parts.join('&') : nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Raises exception Net::XXX (http error code) if an http error occured
|
|
64
|
+
def handle_response!(response) #:nodoc:
|
|
65
|
+
case response
|
|
66
|
+
when Net::HTTPSuccess
|
|
67
|
+
parse_response(response.body)
|
|
68
|
+
when Net::HTTPRedirection
|
|
69
|
+
options[:limit] -= 1
|
|
70
|
+
self.path = response['location']
|
|
71
|
+
perform
|
|
72
|
+
else
|
|
73
|
+
response.instance_eval { class << self; attr_accessor :body_parsed; end }
|
|
74
|
+
begin; response.body_parsed = parse_response(response.body); rescue; end
|
|
75
|
+
response.error! # raises exception corresponding to http error Net::XXX
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def parse_response(body) #:nodoc:
|
|
80
|
+
return nil if body.nil? or body.empty?
|
|
81
|
+
case options[:format]
|
|
82
|
+
when :xml
|
|
83
|
+
Hash.from_xml(body)
|
|
84
|
+
when :json
|
|
85
|
+
ActiveSupport::JSON.decode(body)
|
|
86
|
+
else
|
|
87
|
+
body
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Uses the HTTP Content-Type header to determine the format of the response
|
|
92
|
+
# It compares the MIME type returned to the types stored in the AllowedFormats hash
|
|
93
|
+
def format_from_mimetype(mimetype) #:nodoc:
|
|
94
|
+
AllowedFormats.each { |k, v| return k if mimetype.include?(v) }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def validate! #:nodoc:
|
|
98
|
+
raise HTTParty::RedirectionTooDeep, 'HTTP redirects too deep' if options[:limit].to_i <= 0
|
|
99
|
+
raise ArgumentError, 'only get, post, put and delete methods are supported' unless SupportedHTTPMethods.include?(http_method)
|
|
100
|
+
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].is_a?(Hash)
|
|
101
|
+
raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].is_a?(Hash)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
data/lib/httparty.rb
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'net/https'
|
|
3
|
+
require 'uri'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
require 'rubygems'
|
|
6
|
+
require 'active_support'
|
|
7
|
+
|
|
8
|
+
directory = File.dirname(__FILE__)
|
|
9
|
+
$:.unshift(directory) unless $:.include?(directory) || $:.include?(File.expand_path(directory))
|
|
10
|
+
|
|
11
|
+
require 'httparty/request'
|
|
12
|
+
|
|
13
|
+
module HTTParty
|
|
14
|
+
class UnsupportedFormat < StandardError; end
|
|
15
|
+
class RedirectionTooDeep < StandardError; end
|
|
16
|
+
|
|
17
|
+
AllowedFormats = {:xml => 'text/xml', :json => 'application/json', :html => 'text/html'}
|
|
18
|
+
|
|
19
|
+
def self.included(base)
|
|
20
|
+
base.extend ClassMethods
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module ClassMethods
|
|
24
|
+
def default_options
|
|
25
|
+
@@default_options ||= {}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
# Set an http proxy
|
|
30
|
+
#
|
|
31
|
+
# class Twitter
|
|
32
|
+
# include HTTParty
|
|
33
|
+
# http_proxy 'http://myProxy', 1080
|
|
34
|
+
# ....
|
|
35
|
+
def http_proxy(addr=nil, port = nil)
|
|
36
|
+
default_options[:http_proxyaddr] = addr
|
|
37
|
+
default_options[:http_proxyport] = port
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def base_uri(uri=nil)
|
|
41
|
+
return default_options[:base_uri] unless uri
|
|
42
|
+
default_options[:base_uri] = normalize_base_uri(uri)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def basic_auth(u, p)
|
|
46
|
+
default_options[:basic_auth] = {:username => u, :password => p}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def default_params(h={})
|
|
50
|
+
raise ArgumentError, 'Default params must be a hash' unless h.is_a?(Hash)
|
|
51
|
+
default_options[:default_params] ||= {}
|
|
52
|
+
default_options[:default_params].merge!(h)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def headers(h={})
|
|
56
|
+
raise ArgumentError, 'Headers must be a hash' unless h.is_a?(Hash)
|
|
57
|
+
default_options[:headers] ||= {}
|
|
58
|
+
default_options[:headers].merge!(h)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def format(f)
|
|
62
|
+
raise UnsupportedFormat, "Must be one of: #{AllowedFormats.keys.join(', ')}" unless AllowedFormats.key?(f)
|
|
63
|
+
default_options[:format] = f
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def get(path, options={})
|
|
67
|
+
perform_request Net::HTTP::Get, path, options
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def post(path, options={})
|
|
71
|
+
perform_request Net::HTTP::Post, path, options
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def put(path, options={})
|
|
75
|
+
perform_request Net::HTTP::Put, path, options
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def delete(path, options={})
|
|
79
|
+
perform_request Net::HTTP::Delete, path, options
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
def perform_request(http_method, path, options) #:nodoc:
|
|
84
|
+
Request.new(http_method, path, default_options.merge(options)).perform
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Makes it so uri is sure to parse stuff like google.com without the http
|
|
88
|
+
def normalize_base_uri(url) #:nodoc:
|
|
89
|
+
use_ssl = (url =~ /^https/) || url.include?(':443')
|
|
90
|
+
url.chop! if url.ends_with?('/')
|
|
91
|
+
url.gsub!(/^https?:\/\//i, '')
|
|
92
|
+
"http#{'s' if use_ssl}://#{url}"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Figure out the Content-Type from the path extension
|
|
96
|
+
def format_from_path(path) #:nodoc:
|
|
97
|
+
case path
|
|
98
|
+
when /\.xml$/
|
|
99
|
+
'xml'
|
|
100
|
+
when /\.json$/
|
|
101
|
+
'json'
|
|
102
|
+
else
|
|
103
|
+
nil
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
data/script/console
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# File: script/console
|
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
|
4
|
+
|
|
5
|
+
libs = " -r irb/completion"
|
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/httparty.rb'}"
|
|
9
|
+
puts "Loading httparty gem"
|
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'rubigen'
|
|
6
|
+
rescue LoadError
|
|
7
|
+
require 'rubygems'
|
|
8
|
+
require 'rubigen'
|
|
9
|
+
end
|
|
10
|
+
require 'rubigen/scripts/destroy'
|
|
11
|
+
|
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|