http-security 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +21 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +17 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +20 -0
- data/README.md +90 -0
- data/Rakefile +34 -0
- data/http-security.gemspec +23 -0
- data/lib/http/security.rb +2 -0
- data/lib/http/security/exceptions.rb +8 -0
- data/lib/http/security/headers.rb +12 -0
- data/lib/http/security/headers/cache_control.rb +36 -0
- data/lib/http/security/headers/content_security_policy.rb +71 -0
- data/lib/http/security/headers/content_security_policy_report_only.rb +10 -0
- data/lib/http/security/headers/pragma.rb +24 -0
- data/lib/http/security/headers/public_key_pins.rb +60 -0
- data/lib/http/security/headers/public_key_pins_report_only.rb +10 -0
- data/lib/http/security/headers/set_cookie.rb +75 -0
- data/lib/http/security/headers/strict_transport_security.rb +29 -0
- data/lib/http/security/headers/x_content_type_options.rb +24 -0
- data/lib/http/security/headers/x_frame_options.rb +39 -0
- data/lib/http/security/headers/x_permitted_cross_domain_policies.rb +47 -0
- data/lib/http/security/headers/x_xss_protection.rb +34 -0
- data/lib/http/security/http_date.rb +13 -0
- data/lib/http/security/malformed_header.rb +33 -0
- data/lib/http/security/parsers.rb +14 -0
- data/lib/http/security/parsers/cache_control.rb +62 -0
- data/lib/http/security/parsers/content_security_policy.rb +128 -0
- data/lib/http/security/parsers/content_security_policy_report_only.rb +10 -0
- data/lib/http/security/parsers/expires.rb +19 -0
- data/lib/http/security/parsers/parser.rb +408 -0
- data/lib/http/security/parsers/pragma.rb +25 -0
- data/lib/http/security/parsers/public_key_pins.rb +43 -0
- data/lib/http/security/parsers/public_key_pins_report_only.rb +10 -0
- data/lib/http/security/parsers/set_cookie.rb +62 -0
- data/lib/http/security/parsers/strict_transport_security.rb +42 -0
- data/lib/http/security/parsers/x_content_type_options.rb +19 -0
- data/lib/http/security/parsers/x_frame_options.rb +47 -0
- data/lib/http/security/parsers/x_permitted_cross_domain_policies.rb +33 -0
- data/lib/http/security/parsers/x_xss_protection.rb +27 -0
- data/lib/http/security/response.rb +323 -0
- data/lib/http/security/version.rb +5 -0
- data/spec/data/alexa.csv +100 -0
- data/spec/headers/cache_control_spec.rb +40 -0
- data/spec/headers/content_security_policy_spec.rb +46 -0
- data/spec/headers/pragma_spec.rb +26 -0
- data/spec/headers/public_key_pins_spec.rb +68 -0
- data/spec/headers/set_cookie_spec.rb +122 -0
- data/spec/headers/strict_transport_security_spec.rb +39 -0
- data/spec/headers/x_content_type_options_spec.rb +26 -0
- data/spec/headers/x_frame_options_spec.rb +86 -0
- data/spec/headers/x_permitted_cross_domain_policies_spec.rb +108 -0
- data/spec/headers/x_xss_protection_spec.rb +59 -0
- data/spec/parsers/cache_control_spec.rb +26 -0
- data/spec/parsers/content_security_policy_report_only_spec.rb +48 -0
- data/spec/parsers/content_security_policy_spec.rb +74 -0
- data/spec/parsers/expires_spec.rb +71 -0
- data/spec/parsers/parser_spec.rb +317 -0
- data/spec/parsers/pragma_spec.rb +10 -0
- data/spec/parsers/public_key_pins_spec.rb +81 -0
- data/spec/parsers/set_cookie_spec.rb +55 -0
- data/spec/parsers/strict_transport_security_spec.rb +62 -0
- data/spec/parsers/x_content_type_options_spec.rb +10 -0
- data/spec/parsers/x_frame_options_spec.rb +24 -0
- data/spec/parsers/x_permitted_cross_domain_policies_spec.rb +34 -0
- data/spec/parsers/x_xss_protection_spec.rb +39 -0
- data/spec/response_spec.rb +262 -0
- data/spec/spec_helper.rb +13 -0
- data/tasks/alexa.rb +40 -0
- metadata +171 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/x_content_type_options'
|
3
|
+
|
4
|
+
describe HTTP::Security::Headers::XContentTypeOptions do
|
5
|
+
subject { described_class.new(nosniff: true) }
|
6
|
+
|
7
|
+
describe "no_sniff?" do
|
8
|
+
context "when nosniff: was true" do
|
9
|
+
subject { described_class.new(nosniff: true) }
|
10
|
+
|
11
|
+
it { expect(subject.no_sniff?).to be true }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when nosniff: was false" do
|
15
|
+
subject { described_class.new(nosniff: false) }
|
16
|
+
|
17
|
+
it { expect(subject.no_sniff?).to be false }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#to_s" do
|
22
|
+
it "should return a string" do
|
23
|
+
expect(subject.to_s).to be == "nosniff"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/x_frame_options'
|
3
|
+
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
describe HTTP::Security::Headers::XFrameOptions do
|
7
|
+
let(:allow_from) { URI('http://example.com/') }
|
8
|
+
|
9
|
+
subject { described_class.new(allow_from: allow_from) }
|
10
|
+
|
11
|
+
describe "#initialize" do
|
12
|
+
context "when allow_from: is passed" do
|
13
|
+
it "should set allow_from" do
|
14
|
+
expect(subject.allow_from).to be allow_from
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "deny?" do
|
20
|
+
context "when deny: was true" do
|
21
|
+
subject { described_class.new(deny: true) }
|
22
|
+
|
23
|
+
it { expect(subject.deny?).to be true }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when deny: was false" do
|
27
|
+
subject { described_class.new(deny: false) }
|
28
|
+
|
29
|
+
it { expect(subject.deny?).to be false }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "same_origin?" do
|
34
|
+
context "when sameorigin: was true" do
|
35
|
+
subject { described_class.new(sameorigin: true) }
|
36
|
+
|
37
|
+
it { expect(subject.same_origin?).to be true }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when sameorigin: was false" do
|
41
|
+
subject { described_class.new(sameorigin: false) }
|
42
|
+
|
43
|
+
it { expect(subject.same_origin?).to be false }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "allow_all?" do
|
48
|
+
context "when allowall: was true" do
|
49
|
+
subject { described_class.new(allowall: true) }
|
50
|
+
|
51
|
+
it { expect(subject.allow_all?).to be true }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when sameorigin: was false" do
|
55
|
+
subject { described_class.new(allowall: false) }
|
56
|
+
|
57
|
+
it { expect(subject.allow_all?).to be false }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#to_s" do
|
62
|
+
context "when deny: was true" do
|
63
|
+
subject { described_class.new(deny: true) }
|
64
|
+
|
65
|
+
it { expect(subject.to_s).to be == 'DENY' }
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when same_origin: was true" do
|
69
|
+
subject { described_class.new(sameorigin: true) }
|
70
|
+
|
71
|
+
it { expect(subject.to_s).to be == 'SAMEORIGIN' }
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when allow_from: was specified" do
|
75
|
+
subject { described_class.new(allow_from: allow_from) }
|
76
|
+
|
77
|
+
it { expect(subject.to_s).to be == "ALLOW-FROM #{allow_from}" }
|
78
|
+
end
|
79
|
+
|
80
|
+
context "when allowall: was specified" do
|
81
|
+
subject { described_class.new(allowall: allow_from) }
|
82
|
+
|
83
|
+
it { expect(subject.to_s).to be == 'ALLOWALL' }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/x_permitted_cross_domain_policies'
|
3
|
+
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
describe HTTP::Security::Headers::XPermittedCrossDomainPolicies do
|
7
|
+
describe "#none?" do
|
8
|
+
context "when none: was true" do
|
9
|
+
subject { described_class.new(none: true) }
|
10
|
+
|
11
|
+
it { expect(subject.none?).to be true }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when none: was false" do
|
15
|
+
subject { described_class.new(none: false) }
|
16
|
+
|
17
|
+
it { expect(subject.none?).to be false }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#master_only?" do
|
22
|
+
context "when master_only: was true" do
|
23
|
+
subject { described_class.new(master_only: true) }
|
24
|
+
|
25
|
+
it { expect(subject.master_only?).to be true }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when master_only: was false" do
|
29
|
+
subject { described_class.new(master_only: false) }
|
30
|
+
|
31
|
+
it { expect(subject.master_only?).to be false }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#by_content_type?" do
|
36
|
+
context "when by_content_type: was true" do
|
37
|
+
subject { described_class.new(by_content_type: true) }
|
38
|
+
|
39
|
+
it { expect(subject.by_content_type?).to be true }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when by_content_type: was false" do
|
43
|
+
subject { described_class.new(by_content_type: false) }
|
44
|
+
|
45
|
+
it { expect(subject.by_content_type?).to be false }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#by_ftp_filename?" do
|
50
|
+
context "when by_ftp_filename: was true" do
|
51
|
+
subject { described_class.new(by_ftp_filename: true) }
|
52
|
+
|
53
|
+
it { expect(subject.by_ftp_filename?).to be true }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when by_ftp_filename: was false" do
|
57
|
+
subject { described_class.new(by_ftp_filename: false) }
|
58
|
+
|
59
|
+
it { expect(subject.by_ftp_filename?).to be false }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#all?" do
|
64
|
+
context "when all: was true" do
|
65
|
+
subject { described_class.new(all: true) }
|
66
|
+
|
67
|
+
it { expect(subject.all?).to be true }
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when all: was false" do
|
71
|
+
subject { described_class.new(all: false) }
|
72
|
+
|
73
|
+
it { expect(subject.all?).to be false }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#to_s" do
|
78
|
+
context "when none: was true" do
|
79
|
+
subject { described_class.new(none: true) }
|
80
|
+
|
81
|
+
it { expect(subject.to_s).to be == 'none' }
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when master_only: was true" do
|
85
|
+
subject { described_class.new(master_only: true) }
|
86
|
+
|
87
|
+
it { expect(subject.to_s).to be == 'master-only' }
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when by_content_type: was true" do
|
91
|
+
subject { described_class.new(by_content_type: true) }
|
92
|
+
|
93
|
+
it { expect(subject.to_s).to be == 'by-content-type' }
|
94
|
+
end
|
95
|
+
|
96
|
+
context "when by_ftp_filename: was true" do
|
97
|
+
subject { described_class.new(by_ftp_filename: true) }
|
98
|
+
|
99
|
+
it { expect(subject.to_s).to be == 'by-ftp-filename' }
|
100
|
+
end
|
101
|
+
|
102
|
+
context "when all: was true" do
|
103
|
+
subject { described_class.new(all: true) }
|
104
|
+
|
105
|
+
it { expect(subject.to_s).to be == 'all' }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'http/security/headers/x_xss_protection'
|
3
|
+
|
4
|
+
describe HTTP::Security::Headers::XXSSProtection do
|
5
|
+
let(:mode) { 'block' }
|
6
|
+
let(:report_uri) do
|
7
|
+
"/xss-report/25b8988e-64ff-45a8-b0c6-2700fc1e9abd?source%5Baction%5D=index&source%5Bcontroller%5D=shop&source%5Bsection%5D=storefront"
|
8
|
+
end
|
9
|
+
|
10
|
+
subject do
|
11
|
+
described_class.new(
|
12
|
+
enabled: true,
|
13
|
+
mode: mode,
|
14
|
+
report: report_uri
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#initialize" do
|
19
|
+
it "should set mode" do
|
20
|
+
expect(subject.mode).to be mode
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should set report" do
|
24
|
+
expect(subject.report).to be report_uri
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#enabled?" do
|
29
|
+
context "when enabled: was true" do
|
30
|
+
subject { described_class.new(enabled: true) }
|
31
|
+
|
32
|
+
it { expect(subject.enabled?).to be true }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when enabled: was false" do
|
36
|
+
subject { described_class.new(enabled: false) }
|
37
|
+
|
38
|
+
it { expect(subject.enabled?).to be false }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#to_s" do
|
43
|
+
it "should return a string" do
|
44
|
+
expect(subject.to_s).to be == "1; mode=#{mode}; report=#{report_uri}"
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when enabled: was true" do
|
48
|
+
subject { described_class.new(enabled: true) }
|
49
|
+
|
50
|
+
it { expect(subject.to_s).to be == '1' }
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when enabled: was false" do
|
54
|
+
subject { described_class.new(enabled: false) }
|
55
|
+
|
56
|
+
it { expect(subject.to_s).to be == '0' }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "http/security/parsers/cache_control"
|
3
|
+
|
4
|
+
describe Parsers::CacheControl do
|
5
|
+
it "accepts private" do
|
6
|
+
header = 'private'
|
7
|
+
|
8
|
+
expect(subject.parse(header)).to be == {private: true}
|
9
|
+
end
|
10
|
+
|
11
|
+
it "accepts public, max-age=1" do
|
12
|
+
header = "public, max-age=1"
|
13
|
+
|
14
|
+
expect(subject.parse(header)).to be == {public: true, max_age: 1}
|
15
|
+
end
|
16
|
+
|
17
|
+
it "accepts all recommended value: private, max-age=0, no-cache" do
|
18
|
+
header = "private, max-age=0, no-cache"
|
19
|
+
|
20
|
+
expect(subject.parse(header)).to be == {
|
21
|
+
private: true,
|
22
|
+
max_age: 0,
|
23
|
+
no_cache: true
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "http/security/parsers/content_security_policy_report_only"
|
3
|
+
|
4
|
+
describe Parsers::ContentSecurityPolicyReportOnly do
|
5
|
+
it "accepts default-src 'self'" do
|
6
|
+
header = "default-src 'self';"
|
7
|
+
|
8
|
+
expect(subject.parse(header)).to be == {
|
9
|
+
default_src: "'self'"
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
it "accepts default-src 'self'; script-src 'self';" do
|
14
|
+
header = "default-src 'self'; script-src 'self';"
|
15
|
+
|
16
|
+
expect(subject.parse(header)).to be == {
|
17
|
+
default_src: "'self'",
|
18
|
+
script_src: "'self'"
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
it "accepts a domain" do
|
23
|
+
header = "default-src 'self' trustedscripts.foo.com"
|
24
|
+
|
25
|
+
expect(subject.parse(header)).to be == {
|
26
|
+
default_src: "'self' trustedscripts.foo.com"
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "accepts img-src and media-src" do
|
31
|
+
header = "default-src 'self'; img-src 'self' data:; media-src mediastream:"
|
32
|
+
|
33
|
+
expect(subject.parse(header)).to be == {
|
34
|
+
default_src: "'self'",
|
35
|
+
img_src: "'self' data:",
|
36
|
+
media_src: "mediastream:"
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "accepts report URLs" do
|
41
|
+
header = "default-src 'self'; report-uri http://www.example1.com http://www.example2.com"
|
42
|
+
|
43
|
+
expect(subject.parse(header)).to be == {
|
44
|
+
default_src: "'self'",
|
45
|
+
report_uri: [ URI("http://www.example1.com"), URI("http://www.example2.com") ]
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "http/security/parsers/content_security_policy"
|
3
|
+
|
4
|
+
describe Parsers::ContentSecurityPolicy do
|
5
|
+
it "accepts default-src 'self'" do
|
6
|
+
header = "default-src 'self';"
|
7
|
+
|
8
|
+
expect(subject.parse(header)).to be == {
|
9
|
+
default_src: "'self'"
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
it "accepts default-src 'self'; script-src 'self';" do
|
14
|
+
header = "default-src 'self'; script-src 'self';"
|
15
|
+
|
16
|
+
expect(subject.parse(header)).to be == {
|
17
|
+
default_src: "'self'",
|
18
|
+
script_src: "'self'"
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
it "accepts a domain" do
|
23
|
+
header = "default-src 'self' trustedscripts.foo.com"
|
24
|
+
|
25
|
+
expect(subject.parse(header)).to be == {
|
26
|
+
default_src: "'self' trustedscripts.foo.com"
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "accepts img-src and media-src" do
|
31
|
+
header = "default-src 'self'; img-src 'self' data:; media-src mediastream:"
|
32
|
+
|
33
|
+
expect(subject.parse(header)).to be == {
|
34
|
+
default_src: "'self'",
|
35
|
+
img_src: "'self' data:",
|
36
|
+
media_src: "mediastream:"
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "accepts wildcard domains" do
|
41
|
+
header = "default-src 'self'; img-src *; object-src media1.example.com media2.example.com *.cdn.example.com; script-src trustedscripts.example.com"
|
42
|
+
|
43
|
+
expect(subject.parse(header)).to be == {
|
44
|
+
default_src: "'self'",
|
45
|
+
img_src: "*",
|
46
|
+
object_src: "media1.example.com media2.example.com *.cdn.example.com",
|
47
|
+
script_src: "trustedscripts.example.com"
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
it "parses unsafe-inline and unsafe-eval" do
|
52
|
+
header = "default-src https: 'unsafe-inline' 'unsafe-eval'"
|
53
|
+
response = subject.parse(header)
|
54
|
+
|
55
|
+
expect(subject.parse(header)).to be == {
|
56
|
+
default_src: "https: 'unsafe-inline' 'unsafe-eval'"
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
it "parses sandbox" do
|
61
|
+
header = "sandbox token1 token2 token3"
|
62
|
+
response = subject.parse(header)
|
63
|
+
|
64
|
+
expect(subject.parse(header)).to be == {
|
65
|
+
sandbox: "token1 token2 token3"
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "specific URI paths" do
|
70
|
+
header = "default-src default-src 'self'; script-src https://example.com/js/"
|
71
|
+
it "is not inlcuded in CSP 1.0. Enable ext_host_source to parse specific paths."
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "http/security/parsers/expires"
|
3
|
+
|
4
|
+
describe Parsers::Expires do
|
5
|
+
it "parses negative integers" do
|
6
|
+
header = "-1"
|
7
|
+
|
8
|
+
expect(subject.parse(header)).to eq(-1)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "parses 0" do
|
12
|
+
header = "0"
|
13
|
+
|
14
|
+
expect(subject.parse(header)).to eq(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "parses positive integers" do
|
18
|
+
header = "100"
|
19
|
+
|
20
|
+
expect(subject.parse(header)).to eq(100)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "parses rfc1123-date" do
|
24
|
+
header = "Thu, 04 Dec 2015 16:00:00 GMT"
|
25
|
+
date = Date.parse(header)
|
26
|
+
|
27
|
+
expect(subject.parse(header)).to be == Date.parse(header)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "parses rfc850-date" do
|
31
|
+
header = "Thursday, 04-Dec-15 16:00:00 GMT"
|
32
|
+
|
33
|
+
expect(subject.parse(header)).to be == Date.parse(header)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "parses asctime-date format #1" do
|
37
|
+
header = "Thu Dec 04 16:00:00 2015"
|
38
|
+
|
39
|
+
expect(subject.parse(header)).to be == Date.parse(header)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "parses asctime-date format #2" do
|
43
|
+
header = "Thu Dec 4 16:00:00 2015"
|
44
|
+
|
45
|
+
expect(subject.parse(header)).to be == Date.parse(header)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "parses rfc1123-date" do
|
49
|
+
header = "Thu, 04 Dec 2015 16:00:00 GMT"
|
50
|
+
|
51
|
+
expect(subject.parse(header)).to be == Date.parse(header)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "parses rfc850-date" do
|
55
|
+
header = "Thursday, 04-Dec-15 16:00:00 GMT"
|
56
|
+
|
57
|
+
expect(subject.parse(header)).to be == Date.parse(header)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "parses asctime-date format #1" do
|
61
|
+
header = "Thu Dec 04 16:00:00 2015"
|
62
|
+
|
63
|
+
expect(subject.parse(header)).to be == Date.parse(header)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "parses asctime-date format #2" do
|
67
|
+
header = "Thu Dec 4 16:00:00 2015"
|
68
|
+
|
69
|
+
expect(subject.parse(header)).to be == Date.parse(header)
|
70
|
+
end
|
71
|
+
end
|