cm-httpclient 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ A simple HTTP client
2
+ ============================
3
+
4
+ Doc in progress...
@@ -0,0 +1,45 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{httpclient}
5
+ s.version = "1.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["pedro gutierrez"]
9
+ s.date = %q{2009-05-29}
10
+ s.description = %q{a simple httpclient}
11
+ s.email = %q{pedrogutierrez@mac.com}
12
+
13
+ s.files = %w[
14
+ README.md
15
+ httpclient.gemspec
16
+ lib/httpclient.rb
17
+ lib/httpclient/multipart.rb
18
+ lib/httpclient/httpclient.rb
19
+ ]
20
+
21
+
22
+ s.has_rdoc = true
23
+ s.homepage = %q{http://codemutiny.tumblr.com}
24
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
25
+ s.require_paths = ["lib"]
26
+ s.rubyforge_project = %q{cm-httpclient}
27
+ s.rubygems_version = %q{1.0.0}
28
+ s.summary = %q{a simple httpclient}
29
+
30
+ #if s.respond_to? :specification_version then
31
+ # current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
32
+ # s.specification_version = 2
33
+
34
+ # if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
35
+ # s.add_runtime_dependency(%q<mime-types>, [">= 1.15"])
36
+ # s.add_runtime_dependency(%q<diff-lcs>, [">= 1.1.2"])
37
+ # else
38
+ # s.add_dependency(%q<mime-types>, [">= 1.15"])
39
+ # s.add_dependency(%q<diff-lcs>, [">= 1.1.2"])
40
+ # end
41
+ #else
42
+ # s.add_dependency(%q<mime-types>, [">= 1.15"])
43
+ # s.add_dependency(%q<diff-lcs>, [">= 1.1.2"])
44
+ #end
45
+ end
@@ -0,0 +1,181 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+ require 'rexml/document'
4
+ require 'helpers/multipart'
5
+
6
+ class Hash
7
+ def to_s
8
+ s = "{ "
9
+ self.each{ |k, v| s << "#{k} => #{v}, " }
10
+ s.chop!
11
+ s.chop!
12
+ s << " }"
13
+ end
14
+
15
+ def desym!
16
+ r = Hash.new
17
+ self.each do |k, v|
18
+ r[k.to_s]=v.to_s
19
+ end
20
+ self.replace(r)
21
+ end
22
+ end
23
+
24
+ class REXML::Document
25
+
26
+ def method_missing( name, *args )
27
+ self.root.send( name, args )
28
+ end
29
+
30
+ end
31
+
32
+ class REXML::Element
33
+
34
+ def method_missing( name, *args )
35
+ self.get_text( name.to_s ).to_s
36
+ end
37
+
38
+ end
39
+
40
+ class String
41
+
42
+ def to_simple_date
43
+ DateTime.strptime( self, '%Y-%m-%d' ).strftime( '%B %d, %Y ')
44
+ end
45
+
46
+ end
47
+
48
+ module HttpClient
49
+
50
+ def host( host )
51
+ @@host = host
52
+ end
53
+
54
+ def connect( &block )
55
+ uri = URI.parse( @@host )
56
+ h = Net::HTTP.new( uri.host, uri.port )
57
+ if( uri.scheme == 'https' )
58
+ h.use_ssl = uri.scheme
59
+ h.verify_mode = OpenSSL::SSL::VERIFY_NONE
60
+ end
61
+ headers = {}
62
+ headers.merge!( @auth ) if @auth
63
+ headers.desym!
64
+
65
+ block.call( h, headers )
66
+ end
67
+
68
+ def debug( &block )
69
+ @debug = true
70
+ instance_eval( &block )
71
+ @debug = false
72
+ end
73
+
74
+
75
+
76
+ def debug_request( http_method, path, headers, form = nil )
77
+ if @debug
78
+ puts ""
79
+ puts "Request"
80
+ puts "==========================="
81
+ puts "method: #{http_method}"
82
+ puts "path: #{path}"
83
+ puts "headers: #{headers}"
84
+ puts "form: #{form}" if form
85
+ puts ""
86
+ end
87
+ end
88
+
89
+ def debug_response( code, headers, body )
90
+ if @debug
91
+ puts ""
92
+ puts "Response"
93
+ puts "==========================="
94
+ puts "status code: #{code}"
95
+ puts "headers: #{headers}"
96
+ puts "body: #{body}"
97
+ puts ""
98
+ end
99
+ end
100
+
101
+ def retrieve( path, &block )
102
+ connect do |http, headers|
103
+ debug_request( :get, path, headers )
104
+ res = http.get path, headers
105
+ handle_response( res, block )
106
+ end
107
+ end
108
+
109
+ def remove( path, &block )
110
+ connect do |http, headers|
111
+ debug_request( :delete, path, headers )
112
+ res = http.delete path, headers
113
+ handle_response( res, block )
114
+ end
115
+ end
116
+
117
+
118
+ def create( path, form = nil, &block )
119
+ connect do |http, headers|
120
+ data = nil
121
+ headers[ 'Content-Length' ] = '0'
122
+
123
+ if form
124
+ data, extra_headers = Multipart::Post.prepare_query( form )
125
+ headers.merge!( extra_headers )
126
+ headers[ 'Content-Length' ] = data.length.to_s
127
+ end
128
+
129
+ debug_request( :post, path, headers, form )
130
+
131
+ res = http.post path, data, headers
132
+ handle_response( res, block )
133
+ end
134
+ end
135
+
136
+ alias :update :create
137
+
138
+
139
+ def handle_response( res, block = nil )
140
+ code = res.code.to_i
141
+ headers = res.to_hash
142
+ body = res.body
143
+
144
+ debug_response( code, headers, body )
145
+
146
+ if res[ 'Content-Type' ] == 'text/xml'
147
+ body = REXML::Document.new( body )
148
+ end
149
+ if block
150
+ block.call( code, body, headers )
151
+ else
152
+ @obtained_code = code
153
+ @obtained_body = body
154
+ @obtained_headers = headers
155
+ end
156
+ end
157
+
158
+ attr_reader :obtained_code, :obtained_body, :obtained_headers
159
+
160
+ def admin( key, &block )
161
+ if key == nil
162
+ anonymous( &block )
163
+ else
164
+ @auth = { :cmuser => key }
165
+ instance_eval( &block )
166
+ end
167
+ end
168
+
169
+ def user( username, password = nil, &block )
170
+ @auth = { :cmuser => username }
171
+ @auth[ :cmpasswd ] = password if password
172
+ instance_eval( &block )
173
+ end
174
+
175
+ def anonymous( &block )
176
+ @auth = { :cmuser => 'anonymous' }
177
+ instance_eval( &block )
178
+ end
179
+
180
+ end
181
+
@@ -0,0 +1,83 @@
1
+ # Takes a hash of string and file parameters and returns a string of text
2
+ # formatted to be sent as a multipart form post.
3
+ #
4
+ # Author:: Cody Brimhall <mailto:cbrimhall@ucdavis.edu>
5
+ # Created:: 22 Feb 2008
6
+
7
+ require 'rubygems'
8
+ require 'mime/types'
9
+ require 'cgi'
10
+
11
+
12
+ module Multipart
13
+ VERSION = "1.0.0" unless const_defined?(:VERSION)
14
+
15
+ # Formats a given hash as a multipart form post
16
+ # If a hash value responds to :string or :read messages, then it is
17
+ # interpreted as a file and processed accordingly; otherwise, it is assumed
18
+ # to be a string
19
+ class Post
20
+ # We have to pretend like we're a web browser...
21
+ USERAGENT = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6" unless const_defined?(:USERAGENT)
22
+ BOUNDARY = "0123456789ABLEWASIEREISAWELBA9876543210" unless const_defined?(:BOUNDARY)
23
+ CONTENT_TYPE = "multipart/form-data; boundary=#{ BOUNDARY }" unless const_defined?(:CONTENT_TYPE)
24
+ HEADER = { "Content-Type" => CONTENT_TYPE, "User-Agent" => USERAGENT } unless const_defined?(:HEADER)
25
+
26
+ def self.prepare_query(params)
27
+ fp = []
28
+
29
+ params.each do |k, v|
30
+
31
+ k = k.to_s
32
+
33
+ # Are we trying to make a file parameter?
34
+ if v.respond_to?(:path) and v.respond_to?(:read) then
35
+ fp.push(FileParam.new(k, v.path, v.read))
36
+ # We must be trying to make a regular parameter
37
+ else
38
+ fp.push(StringParam.new(k, v))
39
+ end
40
+ end
41
+
42
+ # Assemble the request body using the special multipart format
43
+ query = fp.collect {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("") + "--" + BOUNDARY + "--"
44
+ return query, HEADER
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # Formats a basic string key/value pair for inclusion with a multipart post
51
+ class StringParam
52
+ attr_accessor :k, :v
53
+
54
+ def initialize(k, v)
55
+ @k = k
56
+ @v = v
57
+ end
58
+
59
+ def to_multipart
60
+ return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n"
61
+ end
62
+ end
63
+
64
+ # Formats the contents of a file or string for inclusion with a multipart
65
+ # form post
66
+ class FileParam
67
+ attr_accessor :k, :filename, :content
68
+
69
+ def initialize(k, filename, content)
70
+ @k = k
71
+ @filename = filename
72
+ @content = content
73
+ end
74
+
75
+ def to_multipart
76
+ # If we can tell the possible mime-type from the filename, use the
77
+ # first in the list; otherwise, use "application/octet-stream"
78
+ mime_type = MIME::Types.type_for(filename)[0] || MIME::Types["application/octet-stream"][0]
79
+ return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"; filename=\"#{ filename }\"\r\n" +
80
+ "Content-Type: #{ mime_type.simplified }\r\n\r\n#{ content }\r\n"
81
+ end
82
+ end
83
+ end
data/lib/httpclient.rb ADDED
@@ -0,0 +1,7 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+
4
+ require 'httpclient/multipart'
5
+ require 'httpclient/httpclient'
6
+
7
+ include HttpClient
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cm-httpclient
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - pedro gutierrez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-29 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: a simple httpclient
17
+ email: pedrogutierrez@mac.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.md
26
+ - httpclient.gemspec
27
+ - lib/httpclient.rb
28
+ - lib/httpclient/multipart.rb
29
+ - lib/httpclient/httpclient.rb
30
+ has_rdoc: true
31
+ homepage: http://codemutiny.tumblr.com
32
+ post_install_message:
33
+ rdoc_options:
34
+ - --inline-source
35
+ - --charset=UTF-8
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project: cm-httpclient
53
+ rubygems_version: 1.2.0
54
+ signing_key:
55
+ specification_version: 2
56
+ summary: a simple httpclient
57
+ test_files: []
58
+