http-security 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|