jsl-http_headers 0.0.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.
data/README.rdoc ADDED
@@ -0,0 +1,56 @@
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
+ == Installation
11
+
12
+ Set up your machine to pull gems from gems.github.com if you haven't already. Then:
13
+
14
+ sudo gem install jsl-http_headers
15
+
16
+ == Quick Start
17
+
18
+ Just require the library, create a new HttpHeaders object with the header string and start invoking methods.
19
+
20
+ require 'http_headers'
21
+ h = HttpHeaders.new(header_str)
22
+ h.content_type
23
+ h.etag
24
+ h.set_cookie # Will return an Array of String values if more than one match is found
25
+
26
+ Other methods should just work for arbitrary attributes by lowercasing the attribute name and substituting
27
+ hyphens with underscores.
28
+
29
+ == Implementation
30
+
31
+ HttpHeaders uses ruby's +method_missing+ in order to build queries for the given parameter dynamically, so
32
+ it doesn't need to parse values for every field at the time that the HttpHeader object is instantiated with
33
+ a HTTP header string.
34
+
35
+ == Possible Limitations
36
+
37
+ Some attributes, such as Set-Cookie, may appear listed multiple times in the header. Where this occurs,
38
+ we try to find all instances of the key and return an Array if multiple occurrences are found. Otherwise,
39
+ nothing is done in the case where there are multiple values for a cookie given as values of a particular key -
40
+ at this point the values won't be magically turned into an Array and it will be up to the user to program the
41
+ desired behavior in a client library.
42
+
43
+ == Feedback
44
+
45
+ Please write the author if you have any questions or feedback about this library. Patches are welcome if you have ideas
46
+ about how the behavior of HttpHeaders can be improved for particular cases. Please include specs using the associated
47
+ test suite if you make improvements, and I would also be happy to receive more fixtures consisting of HTTP strings of
48
+ failure cases indicating where the library can be improved.
49
+
50
+ == References
51
+
52
+ * The HTTP Header Field Definitions - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
53
+
54
+ == Author
55
+
56
+ Justin S. Leitgeb, <justin@phq.org>
data/Rakefile ADDED
@@ -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,35 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "http_headers"
3
+ s.version = "0.0.2"
4
+ s.date = "2009-05-22"
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/hashback"
8
+ s.description = "Creates an object from the attributes in a header_str from Curl"
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
+ "lib/http_headers.rb"
21
+ ]
22
+ s.test_files = [
23
+ "spec/http_headers_spec.rb",
24
+ "spec/spec_helper.rb"
25
+ ]
26
+
27
+ s.extra_rdoc_files = [ "README.rdoc" ]
28
+
29
+ s.rdoc_options += [
30
+ '--title', 'HttpHeaders',
31
+ '--main', 'README.rdoc',
32
+ '--line-numbers',
33
+ '--inline-source'
34
+ ]
35
+ end
@@ -0,0 +1,41 @@
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
+ tag.split(/:\W+/)[1]
40
+ end
41
+ 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,70 @@
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
+ end
8
+
9
+ it "should have text/html as the content_type" do
10
+ @h.version.should == 'HTTP/1.1'
11
+ end
12
+
13
+ it "should have 200 OK as the response code" do
14
+ @h.response_code.should == '200 OK'
15
+ end
16
+
17
+ it "should have a nil etag for the first header file" do
18
+ @h.etag.should be_nil
19
+ end
20
+
21
+ it "should have an etag of pnDSjJtGvlc2WrX6VND/w0qxEc8" do
22
+ @h2.etag.should == 'pnDSjJtGvlc2WrX6VND/w0qxEc8'
23
+ end
24
+
25
+ it "should have Fri, 22 May 2009 18:18:08 GMT for date" do
26
+ @h2.date.should == 'Fri, 22 May 2009 18:18:08 GMT'
27
+ end
28
+
29
+ it "should have Fri, 22 May 2009 18:18:08 GMT for expires" do
30
+ @h2.expires.should == 'Fri, 22 May 2009 18:18:08 GMT'
31
+ end
32
+
33
+ it "should have private, max-age=0 for cache_control" do
34
+ @h2.cache_control.should == 'private, max-age=0'
35
+ end
36
+
37
+ it "should have Fri, 22 May 2009 15:35:08 GMT for last_modified" do
38
+ @h2.last_modified.should == 'Fri, 22 May 2009 15:35:08 GMT'
39
+ end
40
+
41
+ it "should have GFE/2.0 for server" do
42
+ @h2.server.should == 'GFE/2.0'
43
+ end
44
+
45
+ it "should have no-cache for pragma" do
46
+ @h.pragma.should == 'no-cache'
47
+ end
48
+
49
+ it "should have chunked for transfer_encoding" do
50
+ @h2.transfer_encoding.should == 'chunked'
51
+ end
52
+
53
+ describe "multi-valued keys like Set-cookie:" do
54
+ before do
55
+ @c = @h.set_cookie
56
+ end
57
+
58
+ it "should return an Array if multiple values are present" do
59
+ @c.should be_a(Array)
60
+ end
61
+
62
+ it "should have three cookies" do
63
+ @c.size.should == 3
64
+ end
65
+
66
+ it "should have adxcs=-; path=/; domain=.nytimes.com as value for one cookie" do
67
+ @c.include?("adxcs=-; path=/; domain=.nytimes.com").should be_true
68
+ end
69
+ end
70
+ 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,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsl-http_headers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Justin Leitgeb
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-22 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Creates an object from the attributes in a header_str from Curl
17
+ email: justin@phq.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - Rakefile
26
+ - http_headers.gemspec
27
+ - LICENSE
28
+ - README.rdoc
29
+ - spec/http_headers_spec.rb
30
+ - spec/fixtures/headers.txt
31
+ - spec/fixtures/headers2.txt
32
+ - lib/http_headers.rb
33
+ has_rdoc: true
34
+ homepage: http://github.com/jsl/hashback
35
+ post_install_message:
36
+ rdoc_options:
37
+ - --title
38
+ - HttpHeaders
39
+ - --main
40
+ - README.rdoc
41
+ - --line-numbers
42
+ - --inline-source
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.2.0
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: Library for parsing the Curl header_str into attributes
64
+ test_files:
65
+ - spec/http_headers_spec.rb
66
+ - spec/spec_helper.rb