http_headers 0.0.2.2

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Justin S. Leitgeb
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.
@@ -0,0 +1,61 @@
1
+ = HttpHeaders
2
+
3
+ HttpHeaders is a library for parsing HTTP-compliant header strings. It was designed to process the
4
+ results from the header_str method on Curl::Easy objects in Ruby, but should work for other HTTP-compliant
5
+ string formats.
6
+
7
+ It correctly parses the content type, response code and most other key-value fields from the HTTP response header,
8
+ including keys that may appear multiple times in the header such as Set-Cookie.
9
+
10
+ While parsing these header strings seems a very easy thing to do, the small variances in HTTP server responses make
11
+ it more challenging to process these strings than it may initially appear. This library tries to account for these
12
+ server variances by including a comprehensive test suite of HTTP header strings that the library has been tested
13
+ against.
14
+
15
+ == Installation
16
+
17
+ Set up your machine to pull gems from gems.github.com if you haven't already. Then:
18
+
19
+ sudo gem install jsl-http_headers
20
+
21
+ == Quick Start
22
+
23
+ Just require the library, create a new HttpHeaders object with the header string and start invoking methods.
24
+
25
+ require 'http_headers'
26
+ h = HttpHeaders.new(header_str)
27
+ h.content_type
28
+ h.etag
29
+ h.set_cookie # Will return an Array of String values if more than one match is found
30
+
31
+ Other methods should just work for arbitrary attributes by lowercasing the attribute name and substituting
32
+ hyphens with underscores.
33
+
34
+ == Implementation Notes
35
+
36
+ HttpHeaders uses ruby's +method_missing+ in order to build queries for the given parameter dynamically, so
37
+ it doesn't need to parse values for every field at the time that the HttpHeader object is instantiated with
38
+ a HTTP header string.
39
+
40
+ == Possible Limitations
41
+
42
+ Some attributes, such as Set-Cookie, may appear listed multiple times in the header. Where this occurs,
43
+ we try to find all instances of the key and return an Array if multiple occurrences are found. Otherwise,
44
+ nothing is done in the case where there are multiple values for a cookie given as values of a particular key -
45
+ at this point the values won't be magically turned into an Array and it will be up to the user to program the
46
+ desired behavior in a client library.
47
+
48
+ == Feedback
49
+
50
+ Please write the author if you have any questions or feedback about this library. Patches are welcome if you have ideas
51
+ about how the behavior of HttpHeaders can be improved for particular cases. Please include specs using the associated
52
+ test suite if you make improvements, and I would also be happy to receive more fixtures consisting of HTTP strings of
53
+ failure cases indicating where the library can be improved.
54
+
55
+ == References
56
+
57
+ * The HTTP Header Field Definitions - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
58
+
59
+ == Author
60
+
61
+ Justin S. Leitgeb, <justin@phq.org>
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require 'rake'
5
+ require 'spec/rake/spectask'
6
+ require 'rake/rdoctask'
7
+
8
+ desc 'Test the plugin.'
9
+ Spec::Rake::SpecTask.new(:spec) do |t|
10
+ t.spec_opts = ["--format", "specdoc", "--colour"]
11
+ t.libs << 'lib'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc "Run all the tests"
16
+ task :default => :spec
17
+
18
+ desc 'Generate documentation for the hashback plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'HTTP Headers'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README.rdoc')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
@@ -0,0 +1,36 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "http_headers"
3
+ s.version = "0.0.2.2"
4
+ s.date = "2009-05-25"
5
+ s.summary = "Library for parsing the Curl header_str into attributes"
6
+ s.email = "justin@phq.org"
7
+ s.homepage = "http://github.com/jsl/http_headers"
8
+ s.description = "Parses a HTTP header string into individual header fields"
9
+ s.has_rdoc = true
10
+ s.authors = ["Justin Leitgeb"]
11
+ s.files = [
12
+ "Rakefile",
13
+ "http_headers.gemspec",
14
+ "LICENSE",
15
+ "README.rdoc",
16
+ "Rakefile",
17
+ "spec/http_headers_spec.rb",
18
+ "spec/fixtures/headers.txt",
19
+ "spec/fixtures/headers2.txt",
20
+ "spec/fixtures/headers3.txt",
21
+ "lib/http_headers.rb"
22
+ ]
23
+ s.test_files = [
24
+ "spec/http_headers_spec.rb",
25
+ "spec/spec_helper.rb"
26
+ ]
27
+
28
+ s.extra_rdoc_files = [ "README.rdoc" ]
29
+
30
+ s.rdoc_options += [
31
+ '--title', 'HttpHeaders',
32
+ '--main', 'README.rdoc',
33
+ '--line-numbers',
34
+ '--inline-source'
35
+ ]
36
+ end
@@ -0,0 +1,44 @@
1
+ # Class HttpHeaders parses a http header_str from Curl::Easy into component parts.
2
+ class HttpHeaders
3
+
4
+ attr_reader :content
5
+
6
+ def initialize(str)
7
+ @content = str.split(/\\r\\n|\n|\r/)
8
+ end
9
+
10
+ def version
11
+ @content[0].match(/HTTP\/\d\.\d/)[0]
12
+ end
13
+
14
+ def response_code
15
+ @content[0].match(/HTTP\/\d\.\d (\d{3}.*)/)[1]
16
+ end
17
+
18
+ def method_missing(sym, *args)
19
+ detect_multi_value_keys(sym)
20
+ end
21
+
22
+ private
23
+
24
+ # Turns the given sym into a String after replacing the '_' character with the '-'
25
+ def method_sym_to_http_key(sym)
26
+ sym.to_s.gsub('_', '-')
27
+ end
28
+
29
+ def detect_multi_value_keys(tag)
30
+ tag = method_sym_to_http_key(tag)
31
+ regexp = /^#{tag}:/i
32
+ results = @content.select{|e| e =~ regexp }.map{|e| value_from(e)}
33
+ results.size <= 1 ? results.first : results
34
+ end
35
+
36
+ # Returns the key from this tag, which should be a string with key separated
37
+ # from val by ':'
38
+ def value_from(tag)
39
+ val = tag.split(/:\s+/)[1]
40
+
41
+ # Value may be surrounded by quotes in some cases. Remove these extra quotes here.
42
+ val =~ /^\"(.*)\"$/ ? $1 : val
43
+ end
44
+ end
@@ -0,0 +1 @@
1
+ HTTP/1.1 200 OK\r\nServer: Sun-ONE-Web-Server/6.1\r\nDate: Fri, 22 May 2009 12:53:02 GMT\r\nContent-type: text/html\r\nSet-cookie: RMID=21167df34c454a16a02ee2e1; expires=Saturday, 22-May-2010 12:53:02 GMT; path=/; domain=.nytimes.com\r\nSet-cookie: adxcs=-; path=/; domain=.nytimes.com\r\nSet-cookie: adxcs=-; path=/; domain=.nytimes.com\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT\r\nCache-control: no-cache\r\nPragma: no-cache\r\nTransfer-encoding: chunked\r\n\r\n
@@ -0,0 +1,11 @@
1
+ HTTP/1.1 200 OK
2
+ Last-Modified: Fri, 22 May 2009 15:35:08 GMT
3
+ ETag: pnDSjJtGvlc2WrX6VND/w0qxEc8
4
+ Content-Type: text/xml; charset=utf-8
5
+ Date: Fri, 22 May 2009 18:18:08 GMT
6
+ Expires: Fri, 22 May 2009 18:18:08 GMT
7
+ Cache-Control: private, max-age=0
8
+ X-Content-Type-Options: nosniff
9
+ Server: GFE/2.0
10
+ Transfer-Encoding: chunked
11
+
@@ -0,0 +1,13 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Mon, 25 May 2009 12:36:53 GMT
3
+ Server: Apache/2
4
+ Last-Modified: Wed, 01 Sep 2004 13:24:52 GMT
5
+ ETag: "1edec-3e3073913b100"
6
+ Accept-Ranges: bytes
7
+ Content-Length: 126444
8
+ Cache-Control: max-age=21600
9
+ Expires: Mon, 25 May 2009 18:36:53 GMT
10
+ P3P: policyref="http://www.w3.org/2001/05/P3P/p3p.xml"
11
+ Connection: close
12
+ Content-Type: text/html; charset=iso-8859-1
13
+
@@ -0,0 +1,77 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ describe HttpHeaders do
4
+ before do
5
+ @h = HttpHeaders.new(File.read(File.join(File.dirname(__FILE__), %w[fixtures headers.txt])))
6
+ @h2 = HttpHeaders.new(File.read(File.join(File.dirname(__FILE__), %w[fixtures headers2.txt])))
7
+ @h3 = HttpHeaders.new(File.read(File.join(File.dirname(__FILE__), %w[fixtures headers3.txt])))
8
+ end
9
+
10
+ it "should have text/html as the content_type" do
11
+ @h.version.should == 'HTTP/1.1'
12
+ end
13
+
14
+ it "should have 200 OK as the response code" do
15
+ @h.response_code.should == '200 OK'
16
+ end
17
+
18
+ it "should have a nil etag for the first header file" do
19
+ @h.etag.should be_nil
20
+ end
21
+
22
+ it "should have an etag of pnDSjJtGvlc2WrX6VND/w0qxEc8" do
23
+ @h2.etag.should == 'pnDSjJtGvlc2WrX6VND/w0qxEc8'
24
+ end
25
+
26
+ # @h3 tests stripping an etag from a value section of a header where the value is wrapped in
27
+ # quotes as given by the HTTP server.
28
+ it "should have an etag of 1edec-3e3073913b100 for headers3" do
29
+ @h3.etag.should == '1edec-3e3073913b100'
30
+ end
31
+
32
+ it "should have Fri, 22 May 2009 18:18:08 GMT for date" do
33
+ @h2.date.should == 'Fri, 22 May 2009 18:18:08 GMT'
34
+ end
35
+
36
+ it "should have Fri, 22 May 2009 18:18:08 GMT for expires" do
37
+ @h2.expires.should == 'Fri, 22 May 2009 18:18:08 GMT'
38
+ end
39
+
40
+ it "should have private, max-age=0 for cache_control" do
41
+ @h2.cache_control.should == 'private, max-age=0'
42
+ end
43
+
44
+ it "should have Fri, 22 May 2009 15:35:08 GMT for last_modified" do
45
+ @h2.last_modified.should == 'Fri, 22 May 2009 15:35:08 GMT'
46
+ end
47
+
48
+ it "should have GFE/2.0 for server" do
49
+ @h2.server.should == 'GFE/2.0'
50
+ end
51
+
52
+ it "should have no-cache for pragma" do
53
+ @h.pragma.should == 'no-cache'
54
+ end
55
+
56
+ it "should have chunked for transfer_encoding" do
57
+ @h2.transfer_encoding.should == 'chunked'
58
+ end
59
+
60
+ describe "multi-valued keys like Set-cookie:" do
61
+ before do
62
+ @c = @h.set_cookie
63
+ end
64
+
65
+ it "should return an Array if multiple values are present" do
66
+ @c.should be_a(Array)
67
+ end
68
+
69
+ it "should have three cookies" do
70
+ @c.size.should == 3
71
+ end
72
+
73
+ it "should have adxcs=-; path=/; domain=.nytimes.com as value for one cookie" do
74
+ @c.include?("adxcs=-; path=/; domain=.nytimes.com").should be_true
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'mocha'
3
+ require 'spec'
4
+
5
+ Spec::Runner.configure do |config|
6
+ config.mock_with(:mocha)
7
+ end
8
+
9
+ require File.join(File.dirname(__FILE__), %w[.. lib http_headers])
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: http_headers
3
+ version: !ruby/object:Gem::Version
4
+ hash: 67
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ - 2
11
+ version: 0.0.2.2
12
+ platform: ruby
13
+ authors:
14
+ - Justin Leitgeb
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2009-05-25 00:00:00 -04:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: Parses a HTTP header string into individual header fields
24
+ email: justin@phq.org
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files:
30
+ - README.rdoc
31
+ files:
32
+ - Rakefile
33
+ - http_headers.gemspec
34
+ - LICENSE
35
+ - README.rdoc
36
+ - spec/http_headers_spec.rb
37
+ - spec/fixtures/headers.txt
38
+ - spec/fixtures/headers2.txt
39
+ - spec/fixtures/headers3.txt
40
+ - lib/http_headers.rb
41
+ - spec/spec_helper.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/jsl/http_headers
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --title
49
+ - HttpHeaders
50
+ - --main
51
+ - README.rdoc
52
+ - --line-numbers
53
+ - --inline-source
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.7
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Library for parsing the Curl header_str into attributes
81
+ test_files:
82
+ - spec/http_headers_spec.rb
83
+ - spec/spec_helper.rb