righttp 0.0.2 → 0.1.1

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/.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.