http_objects 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +56 -0
- data/Rakefile +12 -0
- data/http_objects.gemspec +20 -0
- data/lib/http_objects/hash.rb +51 -0
- data/lib/http_objects/headers/attributes.rb +38 -0
- data/lib/http_objects/headers/directives/cache.rb +80 -0
- data/lib/http_objects/headers/entity.rb +43 -0
- data/lib/http_objects/headers/general.rb +42 -0
- data/lib/http_objects/headers/request.rb +116 -0
- data/lib/http_objects/headers/response.rb +55 -0
- data/lib/http_objects/headers/tools.rb +29 -0
- data/lib/http_objects/headers.rb +27 -0
- data/lib/http_objects/headers_hash.rb +25 -0
- data/lib/http_objects/parameters/basic_rules.rb +62 -0
- data/lib/http_objects/parameters/date_time.rb +19 -0
- data/lib/http_objects/parameters/entity_tags.rb +27 -0
- data/lib/http_objects/parameters/language_tags.rb +16 -0
- data/lib/http_objects/parameters/media_type.rb +29 -0
- data/lib/http_objects/parameters/uri.rb +21 -0
- data/lib/http_objects/parameters.rb +15 -0
- data/lib/http_objects/version.rb +3 -0
- data/lib/http_objects.rb +5 -0
- data/test/http_objects/hash_test.rb +74 -0
- data/test/http_objects/headers/attributes_test.rb +26 -0
- data/test/http_objects/headers/directives/cache_test.rb +72 -0
- data/test/http_objects/headers/entity/allow_test.rb +13 -0
- data/test/http_objects/headers/entity/content_encoding_test.rb +13 -0
- data/test/http_objects/headers/entity/content_language_test.rb +13 -0
- data/test/http_objects/headers/entity/content_lenght_test.rb +13 -0
- data/test/http_objects/headers/entity/content_location_test.rb +13 -0
- data/test/http_objects/headers/entity/content_md5_test.rb +13 -0
- data/test/http_objects/headers/entity/content_type_test.rb +12 -0
- data/test/http_objects/headers/entity/expires_test.rb +12 -0
- data/test/http_objects/headers/entity/last_modified_test.rb +12 -0
- data/test/http_objects/headers/general_test.rb +59 -0
- data/test/http_objects/headers/request/host_test.rb +13 -0
- data/test/http_objects/headers/request/if_match_test.rb +21 -0
- data/test/http_objects/headers/request/if_modified_since_test.rb +13 -0
- data/test/http_objects/headers/request/if_none_match_test.rb +21 -0
- data/test/http_objects/headers/request/if_range_test.rb +21 -0
- data/test/http_objects/headers/request/if_unmodified_since_test.rb +13 -0
- data/test/http_objects/headers/request/max_forwards_test.rb +13 -0
- data/test/http_objects/headers/request/referer_test.rb +13 -0
- data/test/http_objects/headers/response/age_test.rb +13 -0
- data/test/http_objects/headers/response/etag_test.rb +13 -0
- data/test/http_objects/headers/response/location_test.rb +13 -0
- data/test/http_objects/headers/response/retry_after_test.rb +21 -0
- data/test/http_objects/headers/tools_test.rb +28 -0
- data/test/http_objects/headers_hash_test.rb +18 -0
- data/test/http_objects/http_objects_test.rb +4 -0
- data/test/http_objects/parameters/basic_rules_test.rb +73 -0
- data/test/http_objects/parameters/date_time_test.rb +43 -0
- data/test/http_objects/parameters/entity_tags_test.rb +43 -0
- data/test/http_objects/parameters/language_tags_test.rb +36 -0
- data/test/http_objects/parameters/media_type_test.rb +22 -0
- data/test/http_objects/parameters/uri_test.rb +36 -0
- data/test/test_helper.rb +7 -0
- metadata +202 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Roger Leite
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# HttpObjects
|
2
|
+
|
3
|
+
HTTP 1.1 by the spec, specially headers.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'http_objects'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install http_objects
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
``` ruby
|
22
|
+
#require 'rubygems'
|
23
|
+
require 'http_objects'
|
24
|
+
|
25
|
+
headers = HttpObjects::HeadersHash.new
|
26
|
+
|
27
|
+
# it's a normal hash (for normal keys)
|
28
|
+
headers["key"] = "value"
|
29
|
+
|
30
|
+
# for HTTP headers, you have objects
|
31
|
+
headers["Content-Type"] = "text/html;Charset=utf-8"
|
32
|
+
|
33
|
+
# one can check if header exist
|
34
|
+
puts headers.content_type? # => true
|
35
|
+
|
36
|
+
# one can access raw value
|
37
|
+
puts headers.content_type! # => "text/html;Charset=utf-8"
|
38
|
+
|
39
|
+
# one can access the value
|
40
|
+
puts headers.content_type.value # => "text/html"
|
41
|
+
|
42
|
+
# one can read directives
|
43
|
+
puts headers.content_type['charset'] # => "utf-8"
|
44
|
+
|
45
|
+
# finally one can access the object
|
46
|
+
puts headers.content_type.inspect # => #<HttpObjects::EntityHeaders::ContentType ...>
|
47
|
+
|
48
|
+
```
|
49
|
+
|
50
|
+
## Contributing
|
51
|
+
|
52
|
+
1. Fork it
|
53
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
54
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
55
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
56
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require "rake/testtask"
|
4
|
+
|
5
|
+
ENV["RUBYOPT"] = "rubygems" if ENV["RUBYOPT"].nil?
|
6
|
+
|
7
|
+
Rake::TestTask.new do |t|
|
8
|
+
t.libs << "test"
|
9
|
+
t.test_files = FileList['test/http_objects/**/*_test.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
task :default => :test
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/http_objects/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Roger Leite"]
|
6
|
+
gem.email = ["roger.barreto@gmail.com"]
|
7
|
+
gem.description = %q{HTTP 1.1 by the spec, specially headers}
|
8
|
+
gem.summary = %q{HTTP 1.1 by the spec, specially headers}
|
9
|
+
gem.homepage = "https://github.com/rogerleite/http_objects"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
13
|
+
gem.name = "http_objects"
|
14
|
+
gem.require_paths = ["lib"]
|
15
|
+
gem.version = HttpObjects::VERSION
|
16
|
+
|
17
|
+
gem.add_development_dependency "rake"
|
18
|
+
gem.add_development_dependency "minitest", "~> 3"
|
19
|
+
gem.add_development_dependency "minitest-reporters", "~> 0.7.0"
|
20
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module HttpObjects
|
2
|
+
|
3
|
+
class Hash < ::Hash
|
4
|
+
extend HttpObjects::Headers::Attributes
|
5
|
+
|
6
|
+
# Public: Block that creates method based on attribute name.
|
7
|
+
MethodCreator = Proc.new do |name, header|
|
8
|
+
attr_name = name.downcase.gsub("-", "_")
|
9
|
+
self.class_eval(%{
|
10
|
+
def #{attr_name} # def content_type
|
11
|
+
self.fetch("#{name}", nil) # self.fetch("Content-Type", nil)
|
12
|
+
end # end
|
13
|
+
def #{attr_name}! # def content_type!
|
14
|
+
self.#{attr_name}.raw if #{attr_name}? # self.content_type.raw if content_type?
|
15
|
+
end # end
|
16
|
+
def #{attr_name}? # def content_type?
|
17
|
+
!!self.fetch("#{name}", nil) # !!self.fetch("Content-Type", nil)
|
18
|
+
end # end
|
19
|
+
})
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: Register attribute class with *MethodCreator* block.
|
23
|
+
def self.add_attribute(attr_class)
|
24
|
+
register_attribute(attr_class.header_name, attr_class, &MethodCreator)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.new(hash = nil)
|
28
|
+
hash.kind_of?(HttpObjects::Hash) ? hash : super(hash)
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(hash = nil)
|
32
|
+
super()
|
33
|
+
hash.each { |(key, value)| self[key] = value } unless hash.nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Public: Associates key with value. If key is a valid HTTP Header name,
|
37
|
+
# like "Content-Type", it parses as HTTP Object.
|
38
|
+
#
|
39
|
+
# key - key or HTTP Header name.
|
40
|
+
# value - object. If key is HTTP Header name, value should be a String.
|
41
|
+
def []=(key, value)
|
42
|
+
if (header_class = self.class.attributes[key])
|
43
|
+
value = header_class.parse(value)
|
44
|
+
end
|
45
|
+
super(key, value)
|
46
|
+
end
|
47
|
+
alias :store :[]=
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module HttpObjects::Headers
|
2
|
+
|
3
|
+
# Public: Extend this module and you be able to retrieve and register
|
4
|
+
# attributes in your class.
|
5
|
+
#
|
6
|
+
# Examples
|
7
|
+
#
|
8
|
+
# class SampleAttributes
|
9
|
+
# extend HttpObjects::Headers::Attributes
|
10
|
+
# register_attribute "MyAttributeName", MyObject do |object|
|
11
|
+
# # optional hook
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# SampleAttributes.attributes # => {"MyAttributeName" => MyObject}
|
16
|
+
module Attributes
|
17
|
+
|
18
|
+
# Returns Hash of registered attributes.
|
19
|
+
def attributes
|
20
|
+
@attributes ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Public: Register on *attributes*, the pair name and attr_class.
|
24
|
+
#
|
25
|
+
# name - String identifying attribute.
|
26
|
+
# attr_class - Class to identify the attribute.
|
27
|
+
#
|
28
|
+
# Yields name and attr_class informed. Optional.
|
29
|
+
#
|
30
|
+
# Returns nothing.
|
31
|
+
def register_attribute(name, attr_class)
|
32
|
+
attributes[name] = attr_class
|
33
|
+
yield(name, attr_class) if block_given?
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module HttpObjects::Headers
|
2
|
+
module Directives
|
3
|
+
|
4
|
+
BasicRules = HttpObjects::Parameters::BasicRules
|
5
|
+
|
6
|
+
class RawValue < BasicRules::Base
|
7
|
+
def self.parse(value)
|
8
|
+
self.new(value, value)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Cache-Control = "Cache-Control" ":" 1#cache-directive
|
13
|
+
#
|
14
|
+
# cache-directive = cache-request-directive
|
15
|
+
# | cache-response-directive
|
16
|
+
#
|
17
|
+
# cache-request-directive =
|
18
|
+
# "no-cache" ; Section 14.9.1
|
19
|
+
# | "no-store" ; Section 14.9.2
|
20
|
+
# | "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4
|
21
|
+
# | "max-stale" [ "=" delta-seconds ] ; Section 14.9.3
|
22
|
+
# | "min-fresh" "=" delta-seconds ; Section 14.9.3
|
23
|
+
# | "no-transform" ; Section 14.9.5
|
24
|
+
# | "only-if-cached" ; Section 14.9.4
|
25
|
+
# | cache-extension ; Section 14.9.6
|
26
|
+
#
|
27
|
+
# cache-response-directive =
|
28
|
+
# "public" ; Section 14.9.1
|
29
|
+
# | "private" [ "=" <"> 1#field-name <"> ] ; Section 14.9.1
|
30
|
+
# | "no-cache" [ "=" <"> 1#field-name <"> ]; Section 14.9.1
|
31
|
+
# | "no-store" ; Section 14.9.2
|
32
|
+
# | "no-transform" ; Section 14.9.5
|
33
|
+
# | "must-revalidate" ; Section 14.9.4
|
34
|
+
# | "proxy-revalidate" ; Section 14.9.4
|
35
|
+
# | "max-age" "=" delta-seconds ; Section 14.9.3
|
36
|
+
# | "s-maxage" "=" delta-seconds ; Section 14.9.3
|
37
|
+
# | cache-extension ; Section 14.9.6
|
38
|
+
#
|
39
|
+
# cache-extension = token [ "=" ( token | quoted-string ) ]
|
40
|
+
class Cache < HttpObjects::Hash
|
41
|
+
|
42
|
+
# token [ "=" ( token | quoted-string ) ]
|
43
|
+
TOKEN = /([^,=]+)(?:=\s*(?:\"([^\"]*)\"|\'([^\']*)\'|([^,]*)))?/
|
44
|
+
|
45
|
+
attr_reader :raw, :value
|
46
|
+
|
47
|
+
register_attribute "no-cache", RawValue, &MethodCreator
|
48
|
+
register_attribute "no-store", RawValue, &MethodCreator
|
49
|
+
register_attribute "max-age", BasicRules::Digit, &MethodCreator
|
50
|
+
register_attribute "max-stale", BasicRules::Digit, &MethodCreator
|
51
|
+
register_attribute "min-fresh", BasicRules::Digit, &MethodCreator
|
52
|
+
register_attribute "no-transform", RawValue, &MethodCreator
|
53
|
+
register_attribute "only-if-cached", RawValue, &MethodCreator
|
54
|
+
register_attribute "public", RawValue, &MethodCreator
|
55
|
+
register_attribute "private", RawValue, &MethodCreator
|
56
|
+
register_attribute "must-revalidate", RawValue, &MethodCreator
|
57
|
+
register_attribute "proxy-revalidate", RawValue, &MethodCreator
|
58
|
+
register_attribute "s-maxage", BasicRules::Digit, &MethodCreator
|
59
|
+
|
60
|
+
def self.parse(value)
|
61
|
+
cache = self.new(value)
|
62
|
+
value.scan(TOKEN).each do |key, v1, v2, v3|
|
63
|
+
key = key.strip
|
64
|
+
next if key.length.zero?
|
65
|
+
key.downcase!
|
66
|
+
key_value = (v1 || v2 || v3).to_s
|
67
|
+
cache[key] = key_value.strip
|
68
|
+
end
|
69
|
+
cache
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(value)
|
73
|
+
@raw = value
|
74
|
+
@value = value
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module HttpObjects::Headers::Entity
|
2
|
+
|
3
|
+
extend HttpObjects::Headers::Tools
|
4
|
+
|
5
|
+
# 14.7 Allow
|
6
|
+
# Allow: GET, HEAD, PUT
|
7
|
+
Allow = Header("Allow", HttpObjects::Parameters::BasicRules::UpAlpha)
|
8
|
+
|
9
|
+
# 14.11 Content-Encoding
|
10
|
+
# Pending: implement spec
|
11
|
+
ContentEncoding = Header("Content-Encoding", HttpObjects::Parameters::BasicRules::LoAlpha)
|
12
|
+
|
13
|
+
# 14.12 Content-Language
|
14
|
+
# Content-Language: mi, en
|
15
|
+
ContentLanguage = Header("Content-Language", HttpObjects::Parameters::LanguageTags)
|
16
|
+
|
17
|
+
# 14.13 Content-Length
|
18
|
+
# Content-Length: 3495
|
19
|
+
ContentLength = Header("Content-Length", HttpObjects::Parameters::BasicRules::Digit)
|
20
|
+
|
21
|
+
# 14.14 Content-Location
|
22
|
+
ContentLocation = Header("Content-Location", HttpObjects::Parameters::Uri)
|
23
|
+
|
24
|
+
# 14.15 Content-MD5
|
25
|
+
ContentMD5 = Header("Content-MD5", HttpObjects::Parameters::BasicRules::Token)
|
26
|
+
|
27
|
+
# 14.16 Content-Range
|
28
|
+
# Pending: implement spec
|
29
|
+
ContentRange = Header("Content-Range", HttpObjects::Parameters::BasicRules::Token)
|
30
|
+
|
31
|
+
# 14.21 Expires
|
32
|
+
# Expires: Thu, 01 Dec 1994 16:00:00 GMT
|
33
|
+
Expires = Header("Expires", HttpObjects::Parameters::DateTime)
|
34
|
+
|
35
|
+
# 14.23 Content-Type
|
36
|
+
# Content-Type: text/html; charset=ISO-8859-4
|
37
|
+
ContentType = Header("Content-Type", HttpObjects::Parameters::MediaType)
|
38
|
+
|
39
|
+
# Last-Modified
|
40
|
+
# Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
|
41
|
+
LastModified = Header("Last-Modified", HttpObjects::Parameters::DateTime)
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module HttpObjects::Headers::General
|
2
|
+
|
3
|
+
extend HttpObjects::Headers::Tools
|
4
|
+
|
5
|
+
# 14.9 Cache-Control
|
6
|
+
# Pending: implement spec
|
7
|
+
CacheControl = Header("Cache-Control", HttpObjects::Headers::Directives::Cache)
|
8
|
+
|
9
|
+
# 14.10 Connection
|
10
|
+
# Connection: close
|
11
|
+
Connection = Header("Connection", HttpObjects::Parameters::BasicRules::Token)
|
12
|
+
|
13
|
+
# 14.18 Date
|
14
|
+
# Date: Tue, 15 Nov 1994 08:12:31 GMT
|
15
|
+
Date = Header("Date", HttpObjects::Parameters::DateTime)
|
16
|
+
|
17
|
+
# 14.32 Pragma
|
18
|
+
Pragma = Header("Pragma", HttpObjects::Parameters::BasicRules::Token)
|
19
|
+
|
20
|
+
# 14.40 Trailer
|
21
|
+
Trailer = Header("Trailer", HttpObjects::Parameters::BasicRules::Token)
|
22
|
+
|
23
|
+
# 14.41 Transfer-Encoding
|
24
|
+
# Transfer-Encoding: chunked
|
25
|
+
# Pending: implement spec
|
26
|
+
TransferEncoding = Header("Transfer-Encoding", HttpObjects::Parameters::BasicRules::Token)
|
27
|
+
|
28
|
+
# 14.42 Upgrade
|
29
|
+
# Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
|
30
|
+
Upgrade = Header("Upgrade", HttpObjects::Parameters::BasicRules::Token)
|
31
|
+
|
32
|
+
# 14.45 Via
|
33
|
+
# Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
|
34
|
+
# Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
|
35
|
+
# Pending: implement spec
|
36
|
+
Via = Header("Via", HttpObjects::Parameters::BasicRules::Token)
|
37
|
+
|
38
|
+
# 14.46 Warning
|
39
|
+
# Pending: implement spec
|
40
|
+
Warning = Header("Warning", HttpObjects::Parameters::BasicRules::Token)
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module HttpObjects::Headers::Request
|
2
|
+
|
3
|
+
extend HttpObjects::Headers::Tools
|
4
|
+
|
5
|
+
# 14.1 Accept
|
6
|
+
# Accept: audio/*; q=0.2, audio/basic
|
7
|
+
# Pending: implement spec
|
8
|
+
Accept = Header("Accept", HttpObjects::Parameters::BasicRules::Token)
|
9
|
+
|
10
|
+
# 14.2 Accept-Charset
|
11
|
+
# Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
|
12
|
+
# Pending: implement spec
|
13
|
+
AcceptCharset = Header("Accept-Charset", HttpObjects::Parameters::BasicRules::Token)
|
14
|
+
|
15
|
+
# 14.3 Accept-Encoding
|
16
|
+
# Accept-Encoding: compress, gzip
|
17
|
+
# Accept-Encoding:
|
18
|
+
# Accept-Encoding: *
|
19
|
+
# Accept-Encoding: compress;q=0.5, gzip;q=1.0
|
20
|
+
# Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
|
21
|
+
# Pending: implement spec
|
22
|
+
AcceptEncoding = Header("Accept-Encoding", HttpObjects::Parameters::BasicRules::Token)
|
23
|
+
|
24
|
+
# 14.4 Accept-Language
|
25
|
+
# Accept-Language: da, en-gb;q=0.8, en;q=0.7
|
26
|
+
# Pending: implement spec
|
27
|
+
AcceptLanguage = Header("Accept-Language", HttpObjects::Parameters::BasicRules::Token)
|
28
|
+
|
29
|
+
# 14.8 Authorization
|
30
|
+
# Pending: implement spec
|
31
|
+
Authorization = Header("Authorization", HttpObjects::Parameters::BasicRules::Token)
|
32
|
+
|
33
|
+
# 14.20 Expect
|
34
|
+
# Pending: implement spec
|
35
|
+
Expect = Header("Expect", HttpObjects::Parameters::BasicRules::Token)
|
36
|
+
|
37
|
+
# 14.22 From
|
38
|
+
# From: webmaster@w3.org
|
39
|
+
# Pending: implement spec
|
40
|
+
From = Header("From", HttpObjects::Parameters::BasicRules::Token)
|
41
|
+
|
42
|
+
# 14.23 Host
|
43
|
+
# Host: www.w3.org
|
44
|
+
Host = Header("Host", HttpObjects::Parameters::Uri)
|
45
|
+
|
46
|
+
# 14.24 If-Match
|
47
|
+
# If-Match: "xyzzy"
|
48
|
+
# If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
|
49
|
+
# If-Match: *
|
50
|
+
IfMatch = Header("If-Match") do
|
51
|
+
# ( "*" | 1#entity-tag )
|
52
|
+
def self.parse(value)
|
53
|
+
if value == "*"
|
54
|
+
HttpObjects::Parameters::BasicRules::Token.parse("*")
|
55
|
+
else
|
56
|
+
HttpObjects::Parameters::EntityTags.parse(value)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# 14.25 If-Modified-Since
|
62
|
+
# If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
|
63
|
+
IfModifiedSince = Header("If-Modified-Since", HttpObjects::Parameters::DateTime)
|
64
|
+
|
65
|
+
# 14.26 If-None-Match
|
66
|
+
# If-None-Match: "xyzzy"
|
67
|
+
# If-None-Match: W/"xyzzy"
|
68
|
+
# If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
|
69
|
+
# If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
|
70
|
+
# If-None-Match: *
|
71
|
+
IfNoneMatch = Header("If-None-Match", IfMatch)
|
72
|
+
|
73
|
+
# 14.27 If-Range
|
74
|
+
IfRange = Header("If-Range") do
|
75
|
+
# ( entity-tag | HTTP-date )
|
76
|
+
def self.parse(value)
|
77
|
+
result = HttpObjects::Parameters::EntityTags.parse(value)
|
78
|
+
if value != "" && result.value == ""
|
79
|
+
result = HttpObjects::Parameters::DateTime.parse(value)
|
80
|
+
end
|
81
|
+
result
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# 14.28 If-Unmodified-Since
|
86
|
+
# If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
|
87
|
+
IfUnmodifiedSince = Header("If-Unmodified-Since", HttpObjects::Parameters::DateTime)
|
88
|
+
|
89
|
+
# 14.31 Max-Forwards
|
90
|
+
MaxForwards = Header("Max-Forwards", HttpObjects::Parameters::BasicRules::Digit)
|
91
|
+
|
92
|
+
# 14.34 Proxy-Authorization
|
93
|
+
# Pending: implement spec
|
94
|
+
ProxyAuthorization = Header("Proxy-Authorization", HttpObjects::Parameters::BasicRules::Token)
|
95
|
+
|
96
|
+
# 14.35 Range
|
97
|
+
# Pending: implement spec
|
98
|
+
Range = Header("Range", HttpObjects::Parameters::BasicRules::Token)
|
99
|
+
|
100
|
+
# 14.36 Referer
|
101
|
+
# Referer: http://www.w3.org/hypertext/DataSources/Overview.html
|
102
|
+
Referer = Header("Referer", HttpObjects::Parameters::Uri)
|
103
|
+
|
104
|
+
# 14.39 TE
|
105
|
+
# TE: deflate
|
106
|
+
# TE:
|
107
|
+
# TE: trailers, deflate;q=0.5
|
108
|
+
# Pending: implement spec
|
109
|
+
TE = Header("TE", HttpObjects::Parameters::BasicRules::Token)
|
110
|
+
|
111
|
+
# 14.43 User-Agent
|
112
|
+
# User-Agent: CERN-LineMode/2.15 libwww/2.17b3
|
113
|
+
# Pending: implement spec
|
114
|
+
UserAgent = Header("User-Agent", HttpObjects::Parameters::BasicRules::Token)
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module HttpObjects::Headers::Response
|
2
|
+
|
3
|
+
extend HttpObjects::Headers::Tools
|
4
|
+
|
5
|
+
# 14.5 Accept-Ranges
|
6
|
+
# Pending: implement spec
|
7
|
+
AcceptRanges = Header("Accept-Ranges", HttpObjects::Parameters::BasicRules::Token)
|
8
|
+
|
9
|
+
# 14.6 Age
|
10
|
+
Age = Header("Age", HttpObjects::Parameters::BasicRules::Digit)
|
11
|
+
|
12
|
+
# 14.19 ETag
|
13
|
+
# ETag: "xyzzy"
|
14
|
+
# ETag: W/"xyzzy"
|
15
|
+
# ETag: ""
|
16
|
+
ETag = Header("ETag", HttpObjects::Parameters::EntityTags)
|
17
|
+
|
18
|
+
# 14.30 Location
|
19
|
+
# Location: http://www.w3.org/pub/WWW/People.html
|
20
|
+
Location = Header("Location", HttpObjects::Parameters::Uri)
|
21
|
+
|
22
|
+
# 14.36 Proxy-Authenticate
|
23
|
+
# Pending: implement spec
|
24
|
+
ProxyAuthenticate = Header("Proxy-Authenticate", HttpObjects::Parameters::BasicRules::Token)
|
25
|
+
|
26
|
+
# 14.37 Retry-After
|
27
|
+
# Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
|
28
|
+
# Retry-After: 120
|
29
|
+
RetryAfter = Header("Retry-After") do
|
30
|
+
|
31
|
+
# Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds )
|
32
|
+
def self.parse(value)
|
33
|
+
header_obj = HttpObjects::Parameters::DateTime.parse(value)
|
34
|
+
if header_obj.value.nil?
|
35
|
+
header_obj = HttpObjects::Parameters::BasicRules::Digit.parse(value)
|
36
|
+
end
|
37
|
+
header_obj
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# 14.38 Server
|
43
|
+
# Server: CERN/3.0 libwww/2.17
|
44
|
+
# Pending: implement spec
|
45
|
+
Server = Header("Server", HttpObjects::Parameters::BasicRules::Token)
|
46
|
+
|
47
|
+
# 14.44 Vary
|
48
|
+
# Pending: implement spec
|
49
|
+
Vary = Header("Vary", HttpObjects::Parameters::BasicRules::Token)
|
50
|
+
|
51
|
+
# 14.47 WWW-Authenticate
|
52
|
+
# Pending: implement spec
|
53
|
+
WWWAuthenticate = Header("WWW-Authenticate", HttpObjects::Parameters::BasicRules::Token)
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HttpObjects
|
2
|
+
module Headers
|
3
|
+
|
4
|
+
# **Extend** this and be happy declaring HTTP Headers
|
5
|
+
module Tools
|
6
|
+
|
7
|
+
def Header(name, klass = nil, &block)
|
8
|
+
header_class = if block_given?
|
9
|
+
Class.new(&block)
|
10
|
+
else
|
11
|
+
Class.new(klass)
|
12
|
+
end
|
13
|
+
header_class.instance_eval %{
|
14
|
+
def header_name
|
15
|
+
"#{name}"
|
16
|
+
end
|
17
|
+
}
|
18
|
+
header_class
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns Array of Header classes.
|
22
|
+
def headers
|
23
|
+
self.constants.map { |header| self.const_get(header) }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "http_objects/headers/tools"
|
2
|
+
require "http_objects/headers/attributes"
|
3
|
+
require "http_objects/hash"
|
4
|
+
|
5
|
+
require "http_objects/headers/directives/cache"
|
6
|
+
|
7
|
+
require "http_objects/headers/entity"
|
8
|
+
require "http_objects/headers/general"
|
9
|
+
require "http_objects/headers/request"
|
10
|
+
require "http_objects/headers/response"
|
11
|
+
|
12
|
+
module HttpObjects
|
13
|
+
|
14
|
+
module Headers
|
15
|
+
|
16
|
+
# Returns Array of all HTTP Headers
|
17
|
+
def self.headers
|
18
|
+
[HttpObjects::Headers::General,
|
19
|
+
HttpObjects::Headers::Entity,
|
20
|
+
HttpObjects::Headers::Request,
|
21
|
+
HttpObjects::Headers::Response].inject([]) do |headers, header_module|
|
22
|
+
headers.concat(header_module.headers)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module HttpObjects
|
2
|
+
|
3
|
+
# Public: Hash with HTTP Headers methods.
|
4
|
+
#
|
5
|
+
# Examples
|
6
|
+
#
|
7
|
+
# headers = HttpObjects::Headers.new
|
8
|
+
# headers["key"] = "value" # is kind of Hash
|
9
|
+
#
|
10
|
+
# # And for HTTP headers, you have objects
|
11
|
+
# headers["Content-Type"] = "text/html;Charset=utf-8"
|
12
|
+
# headers.content_type? # => true
|
13
|
+
# headers.content_type! # => "text/html;Charset=utf-8"
|
14
|
+
# headers.content_type.value # => "text/html"
|
15
|
+
# headers.content_type['charset'] # => "utf-8"
|
16
|
+
# headers.content_type.inspect # => #<HttpObjects::Headers::MediaType ...>
|
17
|
+
class HeadersHash < HttpObjects::Hash
|
18
|
+
|
19
|
+
HttpObjects::Headers.headers.each do |header|
|
20
|
+
add_attribute(header)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|