-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathspec_common_logger.rb
149 lines (118 loc) · 4.28 KB
/
spec_common_logger.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# frozen_string_literal: true
require_relative 'helper'
require 'logger'
separate_testing do
require_relative '../lib/rack/common_logger'
require_relative '../lib/rack/lint'
require_relative '../lib/rack/mock_request'
end
describe Rack::CommonLogger do
obj = 'foobar'
length = obj.size
app = Rack::Lint.new lambda { |env|
[200,
{ "content-type" => "text/html", "content-length" => length.to_s },
[obj]]}
app_without_length = Rack::Lint.new lambda { |env|
[200,
{ "content-type" => "text/html" },
[]]}
app_with_zero_length = Rack::Lint.new lambda { |env|
[200,
{ "content-type" => "text/html", "content-length" => "0" },
[]]}
app_without_lint = lambda { |env|
[200,
{ "content-type" => "text/html", "content-length" => length.to_s },
[obj]]}
it "log to rack.errors by default" do
res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
res.errors.wont_be :empty?
res.errors.must_match(/"GET \/ HTTP\/1\.1" 200 #{length} /)
end
it "log to anything with +write+" do
log = StringIO.new
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
log.string.must_match(/"GET \/ HTTP\/1\.1" 200 #{length} /)
end
it "work with standard library logger" do
logdev = StringIO.new
log = Logger.new(logdev)
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
logdev.string.must_match(/"GET \/ HTTP\/1\.1" 200 #{length} /)
end
it "log - content length if header is missing" do
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
res.errors.wont_be :empty?
res.errors.must_match(/"GET \/ HTTP\/1\.1" 200 - /)
end
it "log - content length if header is zero" do
res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
res.errors.wont_be :empty?
res.errors.must_match(/"GET \/ HTTP\/1\.1" 200 - /)
end
it "log - records host from X-Forwarded-For header" do
res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/", 'HTTP_X_FORWARDED_FOR' => '203.0.113.0')
res.errors.wont_be :empty?
res.errors.must_match(/203\.0\.113\.0 - /)
end
it "log - records host from RFC 7239 forwarded for header" do
res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/", 'HTTP_FORWARDED' => 'for=203.0.113.0')
res.errors.wont_be :empty?
res.errors.must_match(/203\.0\.113\.0 - /)
end
def with_mock_time(t = 0)
mc = class << Time; self; end
mc.send :alias_method, :old_now, :now
mc.send :define_method, :now do
at(t)
end
yield
ensure
mc.send :undef_method, :now
mc.send :alias_method, :now, :old_now
end
it "log in common log format" do
log = StringIO.new
with_mock_time do
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/", 'QUERY_STRING' => 'foo=bar')
end
md = /- - - \[([^\]]+)\] "(\w+) \/\?foo=bar HTTP\/1\.1" (\d{3}) \d+ ([\d\.]+)/.match(log.string)
md.wont_equal nil
time, method, status, duration = *md.captures
time.must_equal Time.at(0).strftime("%d/%b/%Y:%H:%M:%S %z")
method.must_equal "GET"
status.must_equal "200"
(0..1).must_include duration.to_f
end
it "escapes non printable characters except newline" do
logdev = StringIO.new
log = Logger.new(logdev)
Rack::MockRequest.new(Rack::CommonLogger.new(app_without_lint, log)).request("GET\x1f", "/hello")
logdev.string.must_match(/GET\\x1f \/hello HTTP\/1\.1/)
end
it "log path with PATH_INFO" do
logdev = StringIO.new
log = Logger.new(logdev)
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/hello")
logdev.string.must_match(/"GET \/hello HTTP\/1\.1" 200 #{length} /)
end
it "log path with SCRIPT_NAME" do
logdev = StringIO.new
log = Logger.new(logdev)
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/path", script_name: "/script")
logdev.string.must_match(/"GET \/script\/path HTTP\/1\.1" 200 #{length} /)
end
it "log path with SERVER_PROTOCOL" do
logdev = StringIO.new
log = Logger.new(logdev)
Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/path", http_version: "HTTP/1.0")
logdev.string.must_match(/"GET \/path HTTP\/1\.0" 200 #{length} /)
end
def length
123
end
def self.obj
"hello world"
end
end