righttp 0.0.2 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -19,3 +19,5 @@ rdoc
19
19
  pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
+
23
+ *.gem
data/README.textile ADDED
@@ -0,0 +1,58 @@
1
+ h1. righttp
2
+
3
+ righttp is a lightweigt http client library which is intended to simplify http requests.
4
+
5
+ It is in a very early stage and patches, suggestions and ideas how to improve it are highly appreciated.
6
+
7
+ h2. Usage
8
+
9
+ Currently there is only one way to perform a request:
10
+
11
+ h3. Minimal version
12
+
13
+ bc. request = Rig::HTTP.new( :host => "ruby-lang.org" )
14
+ response = request.send
15
+
16
+ h3. More elaborate version
17
+
18
+ bc. request = Rig::HTTP.new(
19
+ :host => "ruby-lang.org",
20
+ :path => "/en/documentation/",
21
+ :params => {"love" => "true"}
22
+ :method => "GET",
23
+ :header => "x-CUSTOM-HEADER" => "Awesome"
24
+ )
25
+ response = request.send
26
+
27
+ There will be wrapper methods for the different HTTP methods in the future.
28
+ It is also possible to do multipart form POST/PUT requests with multiple
29
+ files attached.
30
+
31
+ h3. Multipart Post
32
+
33
+ bc. request = Rig::HTTP.new(
34
+ :host => "example.org",
35
+ :path => "/posts",
36
+ :params => { "title" => "Oh Hai", "upload" => File.open("/path/to/file.jpg") }
37
+ )
38
+ response = request.send
39
+
40
+ The file will be closed once the multipart is created.
41
+
42
+ h3. Responses
43
+
44
+ When a request is send it returns a Rig::HTTPResponse which has two attributes: header and body
45
+
46
+ h2. Note on Patches/Pull Requests
47
+
48
+ * Fork the project.
49
+ * Make your feature addition or bug fix.
50
+ * Add tests for it. This is important so I don't break it in a
51
+ future version unintentionally.
52
+ * Commit, do not mess with rakefile, version, or history.
53
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
54
+ * Send me a pull request. Bonus points for topic branches.
55
+
56
+ h2. Copyright
57
+
58
+ Copyright (c) 2010 hukl. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.1.1
@@ -0,0 +1,49 @@
1
+ h1. righttp
2
+
3
+ h2. What righttp wants to achieve
4
+
5
+ righttp is intended to provide a simple and clean interface for HTTP requests while allowing to override almost every parameter of the request if it is neccessary.
6
+
7
+ It is not just a wrapper of net/http
8
+
9
+ Its philosophy is to get out of your way. You want to make a quick custom HTTP request? Then just do it like you think it should work.
10
+
11
+ Below you can see the various ways to make a request:
12
+
13
+ h2. Interface
14
+
15
+ bc.. HTTP.get( 'http://foobar.com' )
16
+
17
+ HTTP.get( 'http://foobar.com?foo=bar&baz=bang')
18
+
19
+ HTTP.get( 'http://foobar.com:3000?foo=bar&baz=bang')
20
+
21
+ HTTP.get( 'http://foobar.com', :params => {"foo" => "bar", :baz => "bang"} )
22
+
23
+ HTTP.get(
24
+ 'http://foobar.com',
25
+ :params => {"foo" => "bar", :baz => "bang"}
26
+ )
27
+
28
+ HTTP.get(
29
+ :host => 'foobar.com',
30
+ :path => "/posts",
31
+ :port => 3000
32
+ :params => {"foo" => "bar", :baz => "bang"},
33
+ )
34
+
35
+ HTTP.post( 'foobar.com', :params => {"foo" => "bar"} )
36
+
37
+ HTTP.post(
38
+ 'foobar.com',
39
+ :params => {"foo" => "bar", :attachment => File.open("path/to/file.jpg")}
40
+ )
41
+
42
+ h2. Components
43
+
44
+ * request preparation
45
+ * sending the request
46
+ * parsing the response
47
+
48
+
49
+ { uri = URI::Generic }
data/lib/rig/http.rb CHANGED
@@ -1,178 +1,129 @@
1
1
  require 'socket'
2
+ require 'uri'
3
+ require 'rig/http_response'
4
+ require 'rig/http_header'
5
+ require 'rig/http_body'
6
+ require 'rig/http_exceptions'
2
7
 
3
8
  module Rig
4
9
 
5
10
  CRLF = "\r\n"
11
+ HTTPMethods = %w(GET POST PUT DELETE)
6
12
 
7
13
  class HTTP
14
+ attr_reader :options, :header, :body
8
15
 
9
- attr_reader :tcp_socket, :params, :method, :path
10
-
11
- def initialize options
12
- @host = options[:host] || raise(ArgumentError, "No host specified")
13
- @port = options[:port] || 80
14
- @params = options[:params] || {}
15
- @method = options[:method] || "GET"
16
- @path = options[:path] || "/"
17
- @header = HTTPHeader.new( "" => "#{@method} #{@path} HTTP/1.1" )
18
- @custom_header = HTTPHeader.new( options[:header] || {} )
19
- @body = HTTPBody.new
20
- @tcp_socket = TCPSocket.new( @host, @port )
21
- end
16
+ def initialize *options
17
+ @options = normalize_options( options )
18
+ @body = HTTPBody.new( @options )
22
19
 
23
- def generate_header_and_body
24
- if @method == "GET"
25
- update_path_query_params
26
- else
27
- update_body
28
- end
29
- update_header
20
+ @options.merge!(
21
+ :content_type => @body.content_type,
22
+ :content_length => @body.content_length
23
+ )
24
+
25
+ @header = HTTPHeader.new( @options )
30
26
  end
31
27
 
32
28
  def send
33
29
  begin
34
- generate_header_and_body
35
- @tcp_socket.write( header + body )
36
- response = @tcp_socket.read
30
+ tcp_socket = TCPSocket.new( @options[:host], @options[:port] )
31
+ tcp_socket.write( @header.to_s)# + @body.to_s )
32
+ response = tcp_socket.read
37
33
  rescue => exception
38
34
  puts exception.message
39
35
  ensure
40
- @tcp_socket.close
36
+ tcp_socket.close
41
37
  end
42
38
 
43
- response || exception.message
44
- end
45
-
46
- def update_header
47
- @header.merge!(
48
- "Host" => @host,
49
- "Origin" => "localhost",
50
- "Content-Length" => @body.join.bytes.to_a.length,
51
- "Content-Type" => determine_content_type
52
- ).merge!(
53
- @custom_header
54
- ).merge!(
55
- "Connection" => "close"
56
- )
57
- end
58
-
59
- def update_path_query_params
60
-
61
- end
62
-
63
- def multipart?
64
- if defined? @multipart
65
- @multipart
66
- else
67
- @multipart = @params.values.map(&:class).include?( File )
68
- end
69
- end
70
-
71
- def update_body
72
- if multipart?
73
- create_multipart_body
39
+ HTTPResponse.new( response ) || exception.message
40
+ end
41
+
42
+ def with_body?
43
+ %w(POST PUT).include?( options[:http_method] ) && options[:body]
44
+ end
45
+
46
+ def http_method
47
+ @options[:http_method] || "GET"
48
+ end
49
+
50
+ def normalize_options options
51
+ options.flatten!
52
+
53
+ options = case HTTP.options_mode( options )
54
+ when :simple
55
+ uri = URI.parse( options.first )
56
+ {
57
+ :host => uri.host,
58
+ :port => uri.port,
59
+ :path => uri.path,
60
+ :query => uri.query
61
+ }
62
+ when :mixed
63
+ uri = URI.parse( options.first )
64
+ uri_options = {
65
+ :host => uri.host,
66
+ :port => uri.port,
67
+ :path => uri.path,
68
+ :query => uri.query
69
+ }
70
+ uri_options.merge( options.last )
71
+ when :advanced
72
+ {
73
+ :http_method => options.first[:http_method] || "GET",
74
+ :host => options.first[:host],
75
+ :port => options.first[:port] || 80,
76
+ :path => options.first[:path] || "/",
77
+ :query => options.first[:query]
78
+ }
74
79
  else
75
- create_simple_body
80
+ raise ArgumentError
76
81
  end
77
- end
78
-
79
- def new_text_multipart field_name, text
80
- part = ""
81
- part += "--#{boundary}"
82
- part += CRLF
83
- part += "Content-Disposition: form-data; name=\"#{field_name}\""
84
- part += CRLF
85
- part += CRLF
86
- part += text
87
- part += CRLF
88
- end
89
-
90
- def new_file_multipart field_name, file
91
- content_type = %x[file --mime-type -b #{file.path}].chomp
92
-
93
- part = ""
94
- part += "--#{boundary}"
95
- part += CRLF
96
- part += "Content-Disposition: form-data; name=\"#{field_name}\"; "
97
- part += "filename=\"#{File.basename( file )}\""
98
- part += CRLF
99
- part += "Content-Type: #{content_type}"
100
- part += CRLF
101
- part += CRLF
102
- part += file.read
103
- file.close
104
- part += CRLF
105
- end
106
82
 
107
- def create_multipart_body
108
- @params.each do |key, value|
109
- if value.is_a?( File )
110
- @body << new_file_multipart( key, value )
111
- elsif value.is_a?( String ) || value.responds_to?( :to_s )
112
- @body << new_text_multipart( key, value )
113
- else
114
- raise ArgumentError, "Invalid Parameter Value"
115
- end
83
+ if options[:path].nil? || options[:path].empty?
84
+ options[:path] = "/"
116
85
  end
117
86
 
118
- @body << "--#{boundary}--\r\n"
119
- end
120
-
121
- def create_simple_body
122
- @body << @params.map {|key, value| "#{key}=#{value}"}.join("&")
87
+ options
123
88
  end
124
89
 
125
- def determine_content_type
126
- if multipart?
127
- "multipart/form-data; boundary=#{boundary}"
90
+ def method_missing name, *args, &block
91
+ if options[name]
92
+ return options[name]
128
93
  else
129
- if @method == "POST"
130
- "application/x-www-form-urlencoded; charset=UTF-8"
131
- else
132
- "text/plain"
133
- end
94
+ super
134
95
  end
135
96
  end
136
97
 
137
- def boundary
138
- @boundary ||= "----rigHTTPmultipart#{rand(2**32)}XZWCFOOBAR"
139
- end
140
-
141
- def header
142
- @header.to_s
143
- end
144
-
145
- def body
146
- @body.to_s
98
+ def self.options_mode options
99
+ if options.length == 1 && options.first.is_a?( String )
100
+ :simple
101
+ elsif options.length == 2 && options.map(&:class) == [String, Hash]
102
+ :mixed
103
+ elsif options.length == 1 && options.first.is_a?( Hash )
104
+ :advanced
105
+ else
106
+ :error
107
+ end
147
108
  end
148
- end
149
109
 
150
- class HTTPHeader < Hash
110
+ def self.method_missing name, *args, &block
111
+ name = name.to_s.upcase
151
112
 
152
- def initialize options
153
- super.merge! options
154
- end
155
-
156
- def to_s
157
- header_string = map do |field_name, value|
158
- if field_name == ""
159
- value
160
- else
161
- "#{field_name}: #{value}"
113
+ if HTTPMethods.include?( name )
114
+ case options_mode( args )
115
+ when :simple
116
+ self.new( args.push( :http_method => name ) )
117
+ when :mixed
118
+ args.last.merge!( :http_method => name )
119
+ self.new( args )
120
+ when :advanced
121
+ self.new( args.first.merge( :http_method => name ) )
162
122
  end
123
+ else
124
+ super
163
125
  end
164
-
165
- header_string.join(CRLF) + CRLF + CRLF
166
- end
167
-
168
- end
169
-
170
- class HTTPBody < Array
171
-
172
- def to_s
173
- join
174
126
  end
175
-
176
127
  end
177
128
 
178
129
  end
@@ -0,0 +1,98 @@
1
+ module Rig
2
+ class HTTPBody < Array
3
+
4
+ def initialize options
5
+ @options = options[:body] || {}
6
+ @http_method = options[:http_method]
7
+
8
+ if multipart?
9
+ create_multipart_body
10
+ else
11
+ create_simple_body
12
+ end
13
+ end
14
+
15
+ def content_length
16
+ join.bytes.to_a.length
17
+ end
18
+
19
+ def content_type
20
+ if multipart?
21
+ "multipart/form-data; boundary=#{boundary}"
22
+ else
23
+ if %w(POST PUT).include?( @http_method )
24
+ "application/x-www-form-urlencoded; charset=UTF-8"
25
+ else
26
+ "text/plain"
27
+ end
28
+ end
29
+ end
30
+
31
+ def boundary
32
+ @boundary ||= "----rigHTTPmultipart#{rand(2**32)}XZWCFOOBAR"
33
+ end
34
+
35
+ def multipart?
36
+ if defined? @multipart
37
+ @multipart
38
+ elsif @options
39
+ @multipart = @options.values.any? do |element|
40
+ element.respond_to?( :read )
41
+ end
42
+ else
43
+ @multipart = false
44
+ end
45
+ end
46
+
47
+ def create_simple_body
48
+ push @options.map {|key, value| "#{key}=#{value}"}.join("&")
49
+ end
50
+
51
+ def create_multipart_body
52
+ @options.each do |key, value|
53
+ if value.respond_to?( :read )
54
+ push new_file_multipart( key, value )
55
+ elsif value.is_a?( String ) || value.respond_to?( :to_s )
56
+ push new_text_multipart( key, value )
57
+ else
58
+ raise ArgumentError, "Invalid Parameter Value"
59
+ end
60
+ end
61
+
62
+ push "--#{boundary}--\r\n"
63
+ end
64
+
65
+ def new_text_multipart field_name, text
66
+ part = ""
67
+ part += "--#{boundary}"
68
+ part += CRLF
69
+ part += "Content-Disposition: form-data; name=\"#{field_name}\""
70
+ part += CRLF
71
+ part += CRLF
72
+ part += text
73
+ part += CRLF
74
+ end
75
+
76
+ def new_file_multipart field_name, file
77
+ content_type = %x[file --mime-type -b #{file.path}].chomp
78
+
79
+ part = ""
80
+ part += "--#{boundary}"
81
+ part += CRLF
82
+ part += "Content-Disposition: form-data; name=\"#{field_name}\"; "
83
+ part += "filename=\"#{File.basename( file )}\""
84
+ part += CRLF
85
+ part += "Content-Type: #{content_type}"
86
+ part += CRLF
87
+ part += CRLF
88
+ part += file.read
89
+ file.close
90
+ part += CRLF
91
+ end
92
+
93
+ def to_s
94
+ join
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1 @@
1
+ class NoHostProvided < ArgumentError; end;
@@ -0,0 +1,36 @@
1
+ module Rig
2
+ class HTTPHeader < Hash
3
+
4
+ def initialize options
5
+ http_method = options[:http_method]
6
+ path = options[:path]
7
+
8
+ header = {
9
+ "" => "#{http_method} #{path} HTTP/1.1",
10
+ "Host" => options[:host],
11
+ "Origin" => "localhost",
12
+ "Content-Length" => options[:content_length],
13
+ "Content-Type" => options[:content_type]
14
+ }.merge(
15
+ (options[:custom_header] || {})
16
+ ).merge(
17
+ "Connection" => "close"
18
+ )
19
+
20
+ merge!( header )
21
+ end
22
+
23
+ def to_s
24
+ header_string = map do |field_name, value|
25
+ if field_name == ""
26
+ value
27
+ else
28
+ "#{field_name}: #{value}"
29
+ end
30
+ end
31
+
32
+ header_string.join(CRLF) + CRLF + CRLF
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,54 @@
1
+ require 'ruby-debug'
2
+ module Rig
3
+ class HTTPResponse
4
+
5
+ attr_reader :header, :body
6
+
7
+ def initialize response
8
+ parts = response.split(CRLF + CRLF)
9
+ @header = parts.delete_at( 0 )
10
+ @status = @header.match(/HTTP\/\d.\d\s(\d\d\d)/)[1]
11
+ @body = parts.join
12
+
13
+ parse_header
14
+
15
+ if @header["Transfer-Encoding"] == "chunked"
16
+ parsed_body = ""
17
+ @body = StringIO.new( @body )
18
+ read_chunked( parsed_body )
19
+
20
+ @body = parsed_body
21
+ end
22
+ end
23
+
24
+ def status
25
+ @status ? @status.to_i : 666
26
+ end
27
+
28
+ def parse_header
29
+ status_line = @header[/HTTP\/\d\.\d\s\d\d\d.+\r\n/]
30
+ @header = @header.gsub(status_line, "Status: #{status_line}")
31
+ @header = @header.split(CRLF)
32
+ @header = @header.map { |element| element.split(": ") }
33
+ @header = @header.inject({}) do |result, element|
34
+ result[element.first] = element.last
35
+ result
36
+ end
37
+ end
38
+
39
+ def read_chunked(dest)
40
+ len = nil
41
+ total = 0
42
+ while true
43
+ line = @body.readline
44
+ hexlen = line.slice(/[0-9a-fA-F]+/) or
45
+ raise HTTPBadResponse, "wrong chunk size line: #{line}"
46
+ len = hexlen.hex
47
+ break if len == 0
48
+ @body.read len, dest; total += len
49
+ @body.read 2 # \r\n
50
+ end
51
+ end
52
+
53
+ end
54
+ end
data/righttp.gemspec CHANGED
@@ -5,27 +5,33 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{righttp}
8
- s.version = "0.0.2"
8
+ s.version = "0.1.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["hukl"]
12
- s.date = %q{2010-08-11}
12
+ s.date = %q{2010-08-15}
13
13
  s.description = %q{Why? Because it has to be done!}
14
14
  s.email = %q{contact@smyck.org}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.rdoc"
17
+ "README.textile"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
21
  ".gitignore",
22
22
  "LICENSE",
23
- "README.rdoc",
23
+ "README.textile",
24
24
  "Rakefile",
25
25
  "VERSION",
26
+ "doc/mission.textile",
26
27
  "lib/rig/http.rb",
28
+ "lib/rig/http_body.rb",
29
+ "lib/rig/http_exceptions.rb",
30
+ "lib/rig/http_header.rb",
31
+ "lib/rig/http_response.rb",
27
32
  "lib/righttp.rb",
28
33
  "righttp.gemspec",
34
+ "test/fixtures/yay.gif",
29
35
  "test/helper.rb",
30
36
  "test/test_http.rb"
31
37
  ]
Binary file
data/test/test_http.rb CHANGED
@@ -2,54 +2,195 @@ require 'helper'
2
2
 
3
3
  class TestHttp < Test::Unit::TestCase
4
4
 
5
- test "create the simplest http get object" do
6
- assert_not_nil get = HTTP.new( {:host => "localhost"} )
5
+ test "cannot create HTTP object without any parameters" do
6
+ assert_raise( ArgumentError) { HTTP.new }
7
7
  end
8
8
 
9
- test "to create a http object at least the host must be specified" do
10
- assert_raise(ArgumentError) { get = HTTP.new( {} ) }
9
+ test "request can be built with one argument" do
10
+ assert_not_nil HTTP.new( "http://foobar.com" )
11
11
  end
12
12
 
13
- test "http objects have accessible socket object" do
14
- get = HTTP.new( {:host => "localhost"} )
15
- assert_not_nil get.tcp_socket
13
+ test "request can be built with two or more arguments" do
14
+ assert_not_nil HTTP.new( "http://fooobar.com", :params => { 1 => 2} )
16
15
  end
17
16
 
18
- test "http object has accessible params" do
19
- get = HTTP.new( {:host => "localhost", :params => {"foo" => "bar"}} )
20
- assert_not_nil get.params
21
- assert_equal ({"foo" => "bar"}), get.params
17
+ test "method get" do
18
+ assert_not_nil request = HTTP.get( "http://foobar.com" )
19
+ expected = {
20
+ :host=>"foobar.com",
21
+ :port=>80,
22
+ :path=>"/",
23
+ :http_method=>"GET",
24
+ :query => nil,
25
+ :content_type=>"text/plain",
26
+ :content_length=>0
27
+ }
28
+ assert_equal expected, request.options
22
29
  end
23
30
 
24
- test "http object without params specified returns empty params" do
25
- get = HTTP.new( {:host => "localhost"} )
26
- assert_not_nil get.params
27
- assert_equal ({}), get.params
31
+ test "method post" do
32
+ assert_not_nil request = HTTP.post( "http://foobar.com" )
33
+ expected = {
34
+ :host=>"foobar.com",
35
+ :port=>80,
36
+ :path=>"/",
37
+ :http_method=>"POST",
38
+ :query => nil,
39
+ :content_type=>"application/x-www-form-urlencoded; charset=UTF-8",
40
+ :content_length=>0
41
+ }
42
+ assert_equal expected, request.options
43
+ end
44
+
45
+ test "method put" do
46
+ assert_not_nil request = HTTP.put( "http://foobar.com" )
47
+ expected = {
48
+ :host=>"foobar.com",
49
+ :port=>80,
50
+ :path=>"/",
51
+ :http_method=>"PUT",
52
+ :query => nil,
53
+ :content_type=>"application/x-www-form-urlencoded; charset=UTF-8",
54
+ :content_length=>0
55
+ }
56
+ assert_equal expected, request.options
57
+ end
58
+
59
+ test "method delete" do
60
+ assert_not_nil request = HTTP.delete( "http://foobar.com" )
61
+ expected = {
62
+ :host=>"foobar.com",
63
+ :port=>80,
64
+ :path=>"/",
65
+ :http_method=>"DELETE",
66
+ :query => nil,
67
+ :content_type=>"text/plain",
68
+ :content_length=>0
69
+ }
70
+ assert_equal expected, request.options
71
+ end
72
+
73
+ test "get request with advanced mode" do
74
+ assert_not_nil request = HTTP.new(:host => "foobar.com")
75
+ expected = {
76
+ :host=>"foobar.com",
77
+ :port=>80,
78
+ :path=>"/",
79
+ :http_method=>"GET",
80
+ :query => nil,
81
+ :content_type=>"text/plain",
82
+ :content_length=>0
83
+ }
84
+
85
+ assert_equal expected, request.options
86
+ end
87
+
88
+ test "other missing methods are delegated to super" do
89
+ assert_raise( ArgumentError ) { HTTP.foobar( "http://foobar.com" ) }
90
+ end
91
+
92
+ test "mixed mode get" do
93
+ request = HTTP.get("http://foobar.com", :port => 3000)
94
+ expected = {
95
+ :host=>"foobar.com",
96
+ :port=>3000,
97
+ :path=>"/",
98
+ :http_method=>"GET",
99
+ :query => nil,
100
+ :content_type=>"text/plain",
101
+ :content_length=>0
102
+ }
103
+ assert_equal expected, request.options
104
+ end
105
+
106
+ test "mixed mode get with query params" do
107
+ request = HTTP.get("http://foobar.com?foo=bar", :port => 3000)
108
+ expected = {
109
+ :host=>"foobar.com",
110
+ :port=>3000,
111
+ :path=>"/",
112
+ :http_method=>"GET",
113
+ :query => "foo=bar",
114
+ :content_type=>"text/plain",
115
+ :content_length=>0
116
+ }
117
+ assert_equal expected, request.options
118
+ end
119
+
120
+ test "mixed mode get with query paramsi and inline port" do
121
+ request = HTTP.get("http://foobar.com:3000?foo=bar")
122
+ expected = {
123
+ :host=>"foobar.com",
124
+ :port=>3000,
125
+ :path=>"/",
126
+ :http_method=>"GET",
127
+ :query => "foo=bar",
128
+ :content_type=>"text/plain",
129
+ :content_length=>0
130
+ }
131
+ assert_equal expected, request.options
132
+ end
133
+
134
+ test "mixed mode get with query params and overriding port" do
135
+ request = HTTP.get("http://foobar.com:2323?foo=bar", :port => 3000)
136
+ expected = {
137
+ :host=>"foobar.com",
138
+ :port=>3000,
139
+ :path=>"/",
140
+ :http_method=>"GET",
141
+ :query => "foo=bar",
142
+ :content_type=>"text/plain",
143
+ :content_length=>0
144
+ }
145
+ assert_equal expected, request.options
146
+ end
147
+
148
+ test "if multipart" do
149
+ File.open(File.join(File.dirname(__FILE__), "fixtures", "yay.gif")) do |f|
150
+ request = HTTP.post(
151
+ "http://foo.com",
152
+ :body => {:upload => f}
153
+ )
154
+ assert request.body.multipart?, "Should be multipart"
155
+ end
156
+ end
157
+
158
+ test "if not multipart" do
159
+ request = HTTP.post(
160
+ "http://foo.com",
161
+ :body => {:abstract => "bla", :title => "foo"}
162
+ )
163
+ assert !request.body.multipart?, "Should not be multipart"
164
+ end
165
+
166
+ test "http object has accessible options" do
167
+ get = HTTP.new( {:host => "localhost", :query => {"foo" => "bar"}} )
168
+ assert_not_nil get.options
169
+ assert_equal ({"foo" => "bar"}), get.options[:query]
28
170
  end
29
171
 
30
172
  test "simple http object defaults to method GET" do
31
173
  get = HTTP.new( {:host => "localhost"} )
32
- assert_equal "GET", get.method
174
+ assert_equal "GET", get.http_method
33
175
  end
34
176
 
35
177
  test "method of http object can be overridden" do
36
- post = HTTP.new( {:host => "localhost", :method => "POST"} )
37
- assert_equal "POST", post.method
178
+ post = HTTP.new( {:host => "localhost", :http_method => "POST"} )
179
+ assert_equal "POST", post.http_method
38
180
  end
39
181
 
40
182
  test "path of a http object defaults to index" do
41
183
  get = HTTP.new( {:host => "localhost"} )
42
- assert_equal "/", get.path
184
+ assert_equal "/", get.options[:path]
43
185
  end
44
186
 
45
187
  test "path of http object can be set" do
46
188
  get = HTTP.new( {:host => "localhost", :path => "/posts"} )
47
- assert_equal "/posts", get.path
189
+ assert_equal "/posts", get.options[:path]
48
190
  end
49
191
 
50
192
  test "generate_header_and_body" do
51
193
  get = HTTP.new( {:host => "localhost", :path => "/posts"} )
52
- assert_not_nil get.generate_header_and_body
53
194
 
54
195
  expected = "GET /posts HTTP/1.1\r\n" \
55
196
  "Host: localhost\r\n" \
@@ -58,39 +199,45 @@ class TestHttp < Test::Unit::TestCase
58
199
  "Content-Type: text/plain\r\n" \
59
200
  "Connection: close\r\n\r\n"
60
201
 
61
- assert_equal expected, get.header
202
+ assert_equal expected, get.header.to_s
62
203
  end
63
204
 
64
- test "multipart body gets properly created" do
65
- post = HTTP.new(
66
- :host => "localhost",
67
- :path => "/photos",
68
- :method => "POST",
69
- :params => {
70
- "photo[title]" => "Hello World",
71
- "photo[image]" => File.open("/Users/hukl/Desktop/file1.png"),
72
- "photo[picture]" => File.open("/Users/hukl/Desktop/file2.png")
73
- }
74
- )
75
- post.generate_header_and_body
76
-
77
- post.tcp_socket.write (post.header + post.body)
78
- response = post.tcp_socket.recvfrom(2**16)
79
- status = response.first.match(/HTTP\/1\.1\s(\d\d\d).+$/)[1]
80
-
81
- assert_equal 302, status.to_i
205
+ test "actual get request" do
206
+ request = HTTP.get( "http://www.spiegel.de" )
207
+ response = request.send
208
+ assert_equal 200, response.status
82
209
  end
83
210
 
84
- test "real get request" do
85
- get = HTTP.new(
86
- :host => "localhost",
87
- :path => "/photos"
88
- )
89
-
90
- get.tcp_socket.write (get.header + get.body)
91
- response = get.tcp_socket.recvfrom(2**16)
92
- status = response.first.match(/HTTP\/1\.1\s(\d\d\d).+$/)[1]
93
-
94
- assert_equal 200, status.to_i
95
- end
211
+ #test "multipart body gets properly created" do
212
+ # post = HTTP.new(
213
+ # :host => "localhost",
214
+ # :path => "/photos",
215
+ # :http_method => "POST",
216
+ # :params => {
217
+ # "photo[title]" => "Hello World",
218
+ # "photo[image]" => File.open("/Users/hukl/Desktop/file1.png"),
219
+ # "photo[picture]" => File.open("/Users/hukl/Desktop/file2.png")
220
+ # }
221
+ # )
222
+ # post.generate_header_and_body
223
+
224
+ # post.tcp_socket.write (post.header + post.body)
225
+ # response = post.tcp_socket.recvfrom(2**16)
226
+ # status = response.first.match(/HTTP\/1\.1\s(\d\d\d).+$/)[1]
227
+
228
+ # assert_equal 302, status.to_i
229
+ #end
230
+
231
+ #test "real get request" do
232
+ # get = HTTP.new(
233
+ # :host => "localhost",
234
+ # :path => "/photos"
235
+ # )
236
+
237
+ # get.tcp_socket.write (get.header + get.body)
238
+ # response = get.tcp_socket.recvfrom(2**16)
239
+ # status = response.first.match(/HTTP\/1\.1\s(\d\d\d).+$/)[1]
240
+
241
+ # assert_equal 200, status.to_i
242
+ #end
96
243
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 0
8
- - 2
9
- version: 0.0.2
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - hukl
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-08-11 00:00:00 +02:00
17
+ date: 2010-08-15 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -26,17 +26,23 @@ extensions: []
26
26
 
27
27
  extra_rdoc_files:
28
28
  - LICENSE
29
- - README.rdoc
29
+ - README.textile
30
30
  files:
31
31
  - .document
32
32
  - .gitignore
33
33
  - LICENSE
34
- - README.rdoc
34
+ - README.textile
35
35
  - Rakefile
36
36
  - VERSION
37
+ - doc/mission.textile
37
38
  - lib/rig/http.rb
39
+ - lib/rig/http_body.rb
40
+ - lib/rig/http_exceptions.rb
41
+ - lib/rig/http_header.rb
42
+ - lib/rig/http_response.rb
38
43
  - lib/righttp.rb
39
44
  - righttp.gemspec
45
+ - test/fixtures/yay.gif
40
46
  - test/helper.rb
41
47
  - test/test_http.rb
42
48
  has_rdoc: true
data/README.rdoc DELETED
@@ -1,17 +0,0 @@
1
- = righttp
2
-
3
- Description goes here.
4
-
5
- == Note on Patches/Pull Requests
6
-
7
- * Fork the project.
8
- * Make your feature addition or bug fix.
9
- * Add tests for it. This is important so I don't break it in a
10
- future version unintentionally.
11
- * Commit, do not mess with rakefile, version, or history.
12
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
- * Send me a pull request. Bonus points for topic branches.
14
-
15
- == Copyright
16
-
17
- Copyright (c) 2010 hukl. See LICENSE for details.