Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
caddy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
caddy
Commits
f92a3aa0
Commit
f92a3aa0
authored
Jan 17, 2019
by
Jeffrey Zhao
Committed by
Matt Holt
Jan 16, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gzip: avoid unnecessary allocations when not compressing (#2396)
parent
917534e3
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
31 additions
and
11 deletions
+31
-11
caddyhttp/gzip/gzip.go
caddyhttp/gzip/gzip.go
+29
-9
caddyhttp/gzip/responsefilter.go
caddyhttp/gzip/responsefilter.go
+1
-1
caddyhttp/gzip/responsefilter_test.go
caddyhttp/gzip/responsefilter_test.go
+1
-1
No files found.
caddyhttp/gzip/gzip.go
View file @
f92a3aa0
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
package
gzip
package
gzip
import
(
import
(
"compress/gzip"
"io"
"io"
"net/http"
"net/http"
"strings"
"strings"
...
@@ -65,21 +66,31 @@ outer:
...
@@ -65,21 +66,31 @@ outer:
}
}
}
}
// In order to avoid unused memory allocation, gzip.putWriter only be called when gzip compression happened.
// see https://github.com/mholt/caddy/issues/2395
gz
:=
&
gzipResponseWriter
{
ResponseWriterWrapper
:
&
httpserver
.
ResponseWriterWrapper
{
ResponseWriter
:
w
},
newWriter
:
func
()
io
.
Writer
{
// gzipWriter modifies underlying writer at init,
// gzipWriter modifies underlying writer at init,
// use a discard writer instead to leave ResponseWriter in
// use a discard writer instead to leave ResponseWriter in
// original form.
// original form.
gzipWriter
:=
getWriter
(
c
.
Level
)
return
getWriter
(
c
.
Level
)
defer
putWriter
(
c
.
Level
,
gzipWriter
)
},
gz
:=
&
gzipResponseWriter
{
}
Writer
:
gzipWriter
,
ResponseWriterWrapper
:
&
httpserver
.
ResponseWriterWrapper
{
ResponseWriter
:
w
},
defer
func
()
{
if
gzWriter
,
ok
:=
gz
.
internalWriter
.
(
*
gzip
.
Writer
);
ok
{
putWriter
(
c
.
Level
,
gzWriter
)
}
}
}()
var
rw
http
.
ResponseWriter
var
rw
http
.
ResponseWriter
// if no response filter is used
// if no response filter is used
if
len
(
c
.
ResponseFilters
)
==
0
{
if
len
(
c
.
ResponseFilters
)
==
0
{
// replace discard writer with ResponseWriter
// replace discard writer with ResponseWriter
gzipWriter
.
Reset
(
w
)
if
gzWriter
,
ok
:=
gz
.
Writer
()
.
(
*
gzip
.
Writer
);
ok
{
gzWriter
.
Reset
(
w
)
}
rw
=
gz
rw
=
gz
}
else
{
}
else
{
// wrap gzip writer with ResponseFilterWriter
// wrap gzip writer with ResponseFilterWriter
...
@@ -106,9 +117,10 @@ outer:
...
@@ -106,9 +117,10 @@ outer:
// gzipResponeWriter wraps the underlying Write method
// gzipResponeWriter wraps the underlying Write method
// with a gzip.Writer to compress the output.
// with a gzip.Writer to compress the output.
type
gzipResponseWriter
struct
{
type
gzipResponseWriter
struct
{
io
.
Writer
i
nternalWriter
i
o
.
Writer
*
httpserver
.
ResponseWriterWrapper
*
httpserver
.
ResponseWriterWrapper
statusCodeWritten
bool
statusCodeWritten
bool
newWriter
func
()
io
.
Writer
}
}
// WriteHeader wraps the underlying WriteHeader method to prevent
// WriteHeader wraps the underlying WriteHeader method to prevent
...
@@ -135,9 +147,17 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) {
...
@@ -135,9 +147,17 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) {
if
!
w
.
statusCodeWritten
{
if
!
w
.
statusCodeWritten
{
w
.
WriteHeader
(
http
.
StatusOK
)
w
.
WriteHeader
(
http
.
StatusOK
)
}
}
n
,
err
:=
w
.
Writer
.
Write
(
b
)
n
,
err
:=
w
.
Writer
()
.
Write
(
b
)
return
n
,
err
return
n
,
err
}
}
//Writer use a lazy way to initialize Writer
func
(
w
*
gzipResponseWriter
)
Writer
()
io
.
Writer
{
if
w
.
internalWriter
==
nil
{
w
.
internalWriter
=
w
.
newWriter
()
}
return
w
.
internalWriter
}
// Interface guards
// Interface guards
var
_
httpserver
.
HTTPInterfaces
=
(
*
gzipResponseWriter
)(
nil
)
var
_
httpserver
.
HTTPInterfaces
=
(
*
gzipResponseWriter
)(
nil
)
caddyhttp/gzip/responsefilter.go
View file @
f92a3aa0
...
@@ -82,7 +82,7 @@ func (r *ResponseFilterWriter) WriteHeader(code int) {
...
@@ -82,7 +82,7 @@ func (r *ResponseFilterWriter) WriteHeader(code int) {
if
r
.
shouldCompress
{
if
r
.
shouldCompress
{
// replace discard writer with ResponseWriter
// replace discard writer with ResponseWriter
if
gzWriter
,
ok
:=
r
.
gzipResponseWriter
.
Writer
.
(
*
gzip
.
Writer
);
ok
{
if
gzWriter
,
ok
:=
r
.
gzipResponseWriter
.
Writer
()
.
(
*
gzip
.
Writer
);
ok
{
gzWriter
.
Reset
(
r
.
ResponseWriter
)
gzWriter
.
Reset
(
r
.
ResponseWriter
)
}
}
// use gzip WriteHeader to include and delete
// use gzip WriteHeader to include and delete
...
...
caddyhttp/gzip/responsefilter_test.go
View file @
f92a3aa0
...
@@ -47,7 +47,7 @@ func TestLengthFilter(t *testing.T) {
...
@@ -47,7 +47,7 @@ func TestLengthFilter(t *testing.T) {
for
j
,
filter
:=
range
filters
{
for
j
,
filter
:=
range
filters
{
r
:=
httptest
.
NewRecorder
()
r
:=
httptest
.
NewRecorder
()
r
.
Header
()
.
Set
(
"Content-Length"
,
fmt
.
Sprint
(
ts
.
length
))
r
.
Header
()
.
Set
(
"Content-Length"
,
fmt
.
Sprint
(
ts
.
length
))
wWriter
:=
NewResponseFilterWriter
([]
ResponseFilter
{
filter
},
&
gzipResponseWriter
{
gzip
.
NewWriter
(
r
),
&
httpserver
.
ResponseWriterWrapper
{
ResponseWriter
:
r
},
false
})
wWriter
:=
NewResponseFilterWriter
([]
ResponseFilter
{
filter
},
&
gzipResponseWriter
{
gzip
.
NewWriter
(
r
),
&
httpserver
.
ResponseWriterWrapper
{
ResponseWriter
:
r
},
false
,
nil
})
if
filter
.
ShouldCompress
(
wWriter
)
!=
ts
.
shouldCompress
[
j
]
{
if
filter
.
ShouldCompress
(
wWriter
)
!=
ts
.
shouldCompress
[
j
]
{
t
.
Errorf
(
"Test %v: Expected %v found %v"
,
i
,
ts
.
shouldCompress
[
j
],
filter
.
ShouldCompress
(
r
))
t
.
Errorf
(
"Test %v: Expected %v found %v"
,
i
,
ts
.
shouldCompress
[
j
],
filter
.
ShouldCompress
(
r
))
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment