Commit 2ca0e8f9 authored by Christopher Speller's avatar Christopher Speller Committed by GitHub
Browse files

Updating golang dependancies (#4075)

parent 6d62d65b
......@@ -33,6 +33,7 @@ func SetupEnterprise() *TestHelper {
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
utils.Cfg.RateLimitSettings.EnableRateLimiter = false
utils.DisableDebugLogForTest()
utils.License.Features.SetDefaults()
NewServer()
......@@ -54,6 +55,7 @@ func Setup() *TestHelper {
utils.LoadConfig("config.json")
utils.InitTranslations(utils.Cfg.LocalizationSettings)
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
utils.Cfg.RateLimitSettings.EnableRateLimiter = false
utils.DisableDebugLogForTest()
NewServer()
StartServer()
......
......@@ -10,8 +10,8 @@ import (
"github.com/gorilla/mux"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
"gopkg.in/throttled/throttled.v1"
throttledStore "gopkg.in/throttled/throttled.v1/store"
"gopkg.in/throttled/throttled.v2"
"gopkg.in/throttled/throttled.v2/store/memstore"
"net/http"
"strings"
"time"
......@@ -39,6 +39,31 @@ func NewServer() {
Srv.Router.NotFoundHandler = http.HandlerFunc(Handle404)
}
type VaryBy struct{}
func (m *VaryBy) Key(r *http.Request) string {
return GetIpAddress(r)
}
func initalizeThrottledVaryBy() *throttled.VaryBy {
vary := throttled.VaryBy{}
if utils.Cfg.RateLimitSettings.VaryByRemoteAddr {
vary.RemoteAddr = true
}
if len(utils.Cfg.RateLimitSettings.VaryByHeader) > 0 {
vary.Headers = strings.Fields(utils.Cfg.RateLimitSettings.VaryByHeader)
if utils.Cfg.RateLimitSettings.VaryByRemoteAddr {
l4g.Warn(utils.T("api.server.start_server.rate.warn"))
vary.RemoteAddr = false
}
}
return &vary
}
func StartServer() {
l4g.Info(utils.T("api.server.start_server.starting.info"))
l4g.Info(utils.T("api.server.start_server.listening.info"), utils.Cfg.ServiceSettings.ListenAddress)
......@@ -48,29 +73,33 @@ func StartServer() {
if utils.Cfg.RateLimitSettings.EnableRateLimiter {
l4g.Info(utils.T("api.server.start_server.rate.info"))
vary := throttled.VaryBy{}
if utils.Cfg.RateLimitSettings.VaryByRemoteAddr {
vary.RemoteAddr = true
store, err := memstore.New(utils.Cfg.RateLimitSettings.MemoryStoreSize)
if err != nil {
l4g.Critical(utils.T("api.server.start_server.rate_limiting_memory_store"))
return
}
if len(utils.Cfg.RateLimitSettings.VaryByHeader) > 0 {
vary.Headers = strings.Fields(utils.Cfg.RateLimitSettings.VaryByHeader)
if utils.Cfg.RateLimitSettings.VaryByRemoteAddr {
l4g.Warn(utils.T("api.server.start_server.rate.warn"))
vary.RemoteAddr = false
}
quota := throttled.RateQuota{
MaxRate: throttled.PerSec(utils.Cfg.RateLimitSettings.PerSec),
MaxBurst: 100,
}
th := throttled.RateLimit(throttled.PerSec(utils.Cfg.RateLimitSettings.PerSec), &vary, throttledStore.NewMemStore(utils.Cfg.RateLimitSettings.MemoryStoreSize))
rateLimiter, err := throttled.NewGCRARateLimiter(store, quota)
if err != nil {
l4g.Critical(utils.T("api.server.start_server.rate_limiting_rate_limiter"))
return
}
th.DeniedHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
l4g.Error("%v: code=429 ip=%v", r.URL.Path, GetIpAddress(r))
throttled.DefaultDeniedHandler.ServeHTTP(w, r)
})
httpRateLimiter := throttled.HTTPRateLimiter{
RateLimiter: rateLimiter,
VaryBy: &VaryBy{},
DeniedHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
l4g.Error("%v: Denied due to throttling settings code=429 ip=%v", r.URL.Path, GetIpAddress(r))
throttled.DefaultDeniedHandler.ServeHTTP(w, r)
}),
}
handler = th.Throttle(&CorsWrapper{Srv.Router})
handler = httpRateLimiter.RateLimit(handler)
}
go func() {
......
hash: 5edc1c9990dbfc36e041dcdabeab2dd8fdd0c8b8b0540b54d515a0044f63952c
updated: 2016-09-06T15:41:59.168710473-04:00
hash: 2ae3f557ee3ae097ee45f383aa53330f8f5457ae7c0adabdac123061061eebb4
updated: 2016-09-22T16:28:20.153961185-04:00
imports:
- name: github.com/alecthomas/log4go
version: e5dc62318d9bd58682f1dceb53a4b24e8253682f
- name: github.com/braintree/manners
version: 82a8879fc5fd0381fa8b2d8033b19bf255252088
version: 0b5e6b2c2843f4c83c2a40f96980b09cf4af733c
- name: github.com/dgryski/dgoogauth
version: 67642ac6f9144f6610279e37e7be9af13f1cd668
version: 96977cbd42e27be71f9f731db6634123de7e861a
- name: github.com/disintegration/imaging
version: d8bbae1de109b518dabc98c6c1633eb358c148a4
- name: github.com/garyburd/redigo
version: 8873b2f1995f59d4bcdd2b0dc9858e2cb9bf0c13
subpackages:
- redis
- internal
version: 5b7e22645c93e3f3911b36b7d66bf8799f3eddfd
- name: github.com/go-gorp/gorp
version: 0c9bc0918534d133cedb439a24adc7cbe66e4a9d
- name: github.com/go-ldap/ldap
version: 0e7db8eb77695b5a952f0e5d78df9ab160050c73
version: d0a5ced67b4dc310b9158d63a2c6f9c5ec13f105
- name: github.com/go-sql-driver/mysql
version: 7ebe0a500653eeb1859664bed5e48dec1e164e73
version: a732e14c62dde3285440047bba97581bc472ae18
- name: github.com/goamz/goamz
version: 02d5144a587b982e33b95f484a34164ce6923c99
version: fb002ae75f50beb93874fa6ce2c861e488ce08a0
subpackages:
- aws
- s3
- name: github.com/golang/freetype
version: c67e4d98d212356ec0d9436a1edcbb6eb799f847
version: 38b4c392adc5eed94207994c4848fff99f4ac234
subpackages:
- raster
- truetype
- name: github.com/golang/groupcache
version: 4eab30f13db9d8b25c752e99d1583628ac2fa422
subpackages:
- lru
- name: github.com/gorilla/context
version: a8d44e7d8e4d532b6a27a02dd82abb31cc1b01bd
version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42
- name: github.com/gorilla/handlers
version: 66e6c6f01d8da976ee113437745ca029c2b585a6
version: ee54c7b44cab12289237fb8631314790076e728b
- name: github.com/gorilla/mux
version: 9c19ed558d5df4da88e2ade9c8940d742aef0e7e
version: 0eeaf8392f5b04950925b8a69fe70f110fa7cbfc
- name: github.com/gorilla/websocket
version: 1f512fc3f05332ba7117626cdfb4e07474e58e60
- name: github.com/hashicorp/golang-lru
version: 0a025b7e63adc15a622f29b0b2c4c3848243bbf6
subpackages:
- simplelru
- name: github.com/jehiah/go-strftime
version: 834e15c05a45371503440cc195bbd05c9a0968d9
- name: github.com/lib/pq
version: ee1442bda7bd1b6a84e913bdb421cb1874ec629d
version: 50761b0867bd1d9d069276790bcd4a3bccf2324a
subpackages:
- oid
- name: github.com/mattermost/rsc
version: bbaefb05eaa0389ea712340066837c8ce4d287f9
subpackages:
- gf256
- qr
- qr/coding
- gf256
- name: github.com/mssola/user_agent
version: 8e786bcb38b846e5eb8eb5f036d9144fc7b0a1f8
version: 85b2f5798558a46fc23443c596e781712f4b7792
- name: github.com/nicksnyder/go-i18n
version: 37e5c2de3e03e4b82693e3fcb4a6aa2cc4eb07e3
subpackages:
......@@ -64,47 +59,48 @@ imports:
- i18n/language
- i18n/translation
- name: github.com/NYTimes/gziphandler
version: 63027b26b87e2ae2ce3810393d4b81021cfd3a35
version: f6438dbf4a82c56684964b03956aa727b0d7816b
- name: github.com/pborman/uuid
version: c55201b036063326c5b1b89ccfe45a184973d073
version: a97ce2ca70fa5a848076093f05e639a89ca34d06
- name: github.com/rwcarlsen/goexif
version: 709fab3d192d7c62f86043caff1e7e3fb0f42bd8
subpackages:
- exif
- tiff
- name: github.com/segmentio/analytics-go
version: bdb0aeca8a993b292b85c9ec17b5ce0ff81848c8
version: 2d840d861c322bdf5346ba7917af1c2285e653d3
- name: github.com/segmentio/backo-go
version: 204274ad699c0983a70203a566887f17a717fef4
- name: github.com/vaughan0/go-ini
version: a98ad7ee00ec53921f08832bc06ecf7fd600e6a1
- name: github.com/xtgo/uuid
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
- name: golang.org/x/crypto
version: 1e61df8d9ea476e2e1504cd9a32b40280c7c6c7e
version: 6ab629be5e31660579425a738ba8870beb5b7404
subpackages:
- bcrypt
- blowfish
- name: github.com/xtgo/uuid
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
- name: golang.org/x/image
version: f551d3a6b7fc11df315ad9e18b404280680f8bec
version: bb355ba4424d077d404aafbb59b05776b2e88fa7
subpackages:
- bmp
- tiff
- font
- math/fixed
- tiff
- tiff/lzw
- name: golang.org/x/sys
version: e82cb4d7dffc35bcec7bc8bf9e402377e0ecf3f4
version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
subpackages:
- unix
- name: gopkg.in/asn1-ber.v1
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
- name: gopkg.in/fsnotify.v1
version: 30411dbcefb7a1da7e84f75530ad3abe4011b4f8
- name: gopkg.in/throttled/throttled.v1
version: 74e328a1af88a9b54f9eca1397d74ad98572a6df
version: a8a77c9133d2d6fd8334f3260d06f60e8d80a5fb
- name: gopkg.in/throttled/throttled.v2
version: b5675e93f9d999b22f92d859a5bf2138d3641af4
subpackages:
- store
- store/memstore
- name: gopkg.in/yaml.v2
version: a83829b6f1293c91addabc89d0571c246397bbf4
devImports: []
\ No newline at end of file
version: 31c299268d302dd0aa9a0dcf765a3d58971ac83f
testImports: []
package: github.com/mattermost/platform
import:
- package: github.com/NYTimes/gziphandler
version: f6438dbf4a82c56684964b03956aa727b0d7816b
- package: github.com/alecthomas/log4go
version: e5dc62318d9bd58682f1dceb53a4b24e8253682f
- package: github.com/braintree/manners
version: 0.4.0
- package: github.com/dgryski/dgoogauth
version: 96977cbd42e27be71f9f731db6634123de7e861a
- package: github.com/disintegration/imaging
version: 5b7e22645c93e3f3911b36b7d66bf8799f3eddfd
- package: github.com/go-gorp/gorp
version: 0c9bc0918534d133cedb439a24adc7cbe66e4a9d
version: 0c9bc0918534d133cedb439a24adc7cbe66e4a9d # Keep this locked
- package: github.com/go-ldap/ldap
version: v2.4.1
- package: github.com/go-sql-driver/mysql
version: v1.2
- package: github.com/goamz/goamz
version: fb002ae75f50beb93874fa6ce2c861e488ce08a0
subpackages:
- aws
- s3
- package: github.com/golang/freetype
version: 38b4c392adc5eed94207994c4848fff99f4ac234
- package: github.com/gorilla/handlers
version: v1.1
- package: github.com/gorilla/mux
version: v1.1
- package: github.com/gorilla/websocket
version: v1.0.0
- package: github.com/lib/pq
version: 50761b0867bd1d9d069276790bcd4a3bccf2324a
- package: github.com/mattermost/rsc
subpackages:
- qr
- package: github.com/mssola/user_agent
version: v0.4.1
- package: github.com/nicksnyder/go-i18n
version: v1.4.0
subpackages:
- i18n
- package: github.com/pborman/uuid
version: v1.0
- package: github.com/rwcarlsen/goexif
version: 709fab3d192d7c62f86043caff1e7e3fb0f42bd8
subpackages:
- exif
- package: golang.org/x/crypto
version: 6ab629be5e31660579425a738ba8870beb5b7404
subpackages:
- bcrypt
- package: golang.org/x/image
version: bb355ba4424d077d404aafbb59b05776b2e88fa7
subpackages:
- bmp
- package: gopkg.in/fsnotify.v1
- package: gopkg.in/throttled/throttled.v1
version: v1.3.1
- package: gopkg.in/throttled/throttled.v2
version: v2.0.3
subpackages:
- store
- package: github.com/segmentio/analytics-go
version: 2.1.1
......@@ -1411,6 +1411,14 @@
"id": "api.server.start_server.listening.info",
"translation": "Server is listening on %v"
},
{
"id": "api.server.start_server.rate_limiting_memory_store",
"translation": "Unable to initalize rate limiting memory store. Check MemoryStoreSize config setting."
},
{
"id": "api.server.start_server.rate_limiting_memory_store",
"translation": "Unable to initalize rate limiting."
},
{
"id": "api.server.start_server.rate.info",
"translation": "RateLimiter is enabled"
......
---
layout: code-of-conduct
version: v1.0
---
This code of conduct outlines our expectations for participants within the **NYTimes/gziphandler** community, as well as steps to reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all and expect our code of conduct to be honored. Anyone who violates this code of conduct may be banned from the community.
Our open source community strives to:
* **Be friendly and patient.**
* **Be welcoming**: We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
* **Be considerate**: Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language.
* **Be respectful**: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.
* **Be careful in the words that we choose**: we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable.
* **Try to understand why we disagree**: Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
## Definitions
Harassment includes, but is not limited to:
- Offensive comments related to gender, gender identity and expression, sexual orientation, disability, mental illness, neuro(a)typicality, physical appearance, body size, race, age, regional discrimination, political or religious affiliation
- Unwelcome comments regarding a person’s lifestyle choices and practices, including those related to food, health, parenting, drugs, and employment
- Deliberate misgendering. This includes deadnaming or persistently using a pronoun that does not correctly reflect a person's gender identity. You must address people by the name they give you when not addressing them by their username or handle
- Physical contact and simulated physical contact (eg, textual descriptions like “*hug*” or “*backrub*”) without consent or after a request to stop
- Threats of violence, both physical and psychological
- Incitement of violence towards any individual, including encouraging a person to commit suicide or to engage in self-harm
- Deliberate intimidation
- Stalking or following
- Harassing photography or recording, including logging online activity for harassment purposes
- Sustained disruption of discussion
- Unwelcome sexual attention, including gratuitous or off-topic sexual images or behaviour
- Pattern of inappropriate social contact, such as requesting/assuming inappropriate levels of intimacy with others
- Continued one-on-one communication after requests to cease
- Deliberate “outing” of any aspect of a person’s identity without their consent except as necessary to protect others from intentional abuse
- Publication of non-harassing private communication
Our open source community prioritizes marginalized people’s safety over privileged people’s comfort. We will not act on complaints regarding:
- ‘Reverse’ -isms, including ‘reverse racism,’ ‘reverse sexism,’ and ‘cisphobia’
- Reasonable communication of boundaries, such as “leave me alone,” “go away,” or “I’m not discussing this with you”
- Refusal to explain or debate social justice concepts
- Communicating in a ‘tone’ you don’t find congenial
- Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions
### Diversity Statement
We encourage everyone to participate and are committed to building a community for all. Although we will fail at times, we seek to treat everyone both as fairly and equally as possible. Whenever a participant has made a mistake, we expect them to take responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and respectfully, and do our best to right the wrong.
Although this list cannot be exhaustive, we explicitly honor diversity in age, gender, gender identity or expression, culture, ethnicity, language, national origin, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, and technical ability. We will not tolerate discrimination based on any of the protected
characteristics above, including participants with disabilities.
### Reporting Issues
If you experience or witness unacceptable behavior—or have any other concerns—please report it by contacting us via **code@nytimes.com**. All reports will be handled with discretion. In your report please include:
- Your contact information.
- Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please
include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link.
- Any additional information that may be helpful.
After filing a report, a representative will contact you personally, review the incident, follow up with any additional questions, and make a decision as to how to respond. If the person who is harassing you is part of the response team, they will recuse themselves from handling your incident. If the complaint originates from a member of the response team, it will be handled by a different member of the response team. We will respect confidentiality requests for the purpose of protecting victims of abuse.
### Attribution & Acknowledgements
We all stand on the shoulders of giants across many open source communities. We'd like to thank the communities and projects that established code of conducts and diversity statements as our inspiration:
* [Django](https://www.djangoproject.com/conduct/reporting/)
* [Python](https://www.python.org/community/diversity/)
* [Ubuntu](http://www.ubuntu.com/about/about-ubuntu/conduct)
* [Contributor Covenant](http://contributor-covenant.org/)
* [Geek Feminism](http://geekfeminism.org/about/code-of-conduct/)
* [Citizen Code of Conduct](http://citizencodeofconduct.org/)
This Code of Conduct was based on https://github.com/todogroup/opencodeofconduct
# Contributing to NYTimes/gziphandler
This is an open source project started by handful of developers at The New York Times and open to the entire Go community.
We really appreciate your help!
## Filing issues
When filing an issue, make sure to answer these five questions:
1. What version of Go are you using (`go version`)?
2. What operating system and processor architecture are you using?
3. What did you do?
4. What did you expect to see?
5. What did you see instead?
## Contributing code
Before submitting changes, please follow these guidelines:
1. Check the open issues and pull requests for existing discussions.
2. Open an issue to discuss a new feature.
3. Write tests.
4. Make sure code follows the ['Go Code Review Comments'](https://github.com/golang/go/wiki/CodeReviewComments).
5. Make sure your changes pass `go test`.
6. Make sure the entire test suite passes locally and on Travis CI.
7. Open a Pull Request.
8. [Squash your commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) after receiving feedback and add a [great commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
Unless otherwise noted, the gziphandler source files are distributed under the Apache 2.0-style license found in the LICENSE.md file.
......@@ -13,6 +13,8 @@ const (
vary = "Vary"
acceptEncoding = "Accept-Encoding"
contentEncoding = "Content-Encoding"
contentType = "Content-Type"
contentLength = "Content-Length"
)
type codings map[string]float64
......@@ -22,57 +24,160 @@ type codings map[string]float64
// The examples seem to indicate that it is.
const DEFAULT_QVALUE = 1.0
var gzipWriterPool = sync.Pool{
New: func() interface{} { return gzip.NewWriter(nil) },
// gzipWriterPools stores a sync.Pool for each compression level for reuse of
// gzip.Writers. Use poolIndex to covert a compression level to an index into
// gzipWriterPools.
var gzipWriterPools [gzip.BestCompression - gzip.BestSpeed + 2]*sync.Pool
func init() {
for i := gzip.BestSpeed; i <= gzip.BestCompression; i++ {
addLevelPool(i)
}
addLevelPool(gzip.DefaultCompression)
}
// poolIndex maps a compression level to its index into gzipWriterPools. It
// assumes that level is a valid gzip compression level.
func poolIndex(level int) int {
// gzip.DefaultCompression == -1, so we need to treat it special.
if level == gzip.DefaultCompression {
return gzip.BestCompression - gzip.BestSpeed + 1
}
return level - gzip.BestSpeed
}
func addLevelPool(level int) {
gzipWriterPools[poolIndex(level)] = &sync.Pool{
New: func() interface{} {
// NewWriterLevel only returns error on a bad level, we are guaranteeing
// that this will be a valid level so it is okay to ignore the returned
// error.
w, _ := gzip.NewWriterLevel(nil, level)
return w
},
}
}
// GzipResponseWriter provides an http.ResponseWriter interface, which gzips
// bytes before writing them to the underlying response. This doesn't set the
// Content-Encoding header, nor close the writers, so don't forget to do that.
// bytes before writing them to the underlying response. This doesn't close the
// writers, so don't forget to do that.
type GzipResponseWriter struct {
gw *gzip.Writer
http.ResponseWriter
index int // Index for gzipWriterPools.
gw *gzip.Writer
}
// Write appends data to the gzip writer.
func (w GzipResponseWriter) Write(b []byte) (int, error) {
if _, ok := w.Header()["Content-Type"]; !ok {
func (w *GzipResponseWriter) Write(b []byte) (int, error) {
// Lazily create the gzip.Writer, this allows empty bodies to be actually
// empty, for example in the case of status code 204 (no content).
if w.gw == nil {
w.init()
}
if _, ok := w.Header()[contentType]; !ok {
// If content type is not set, infer it from the uncompressed body.
w.Header().Set("Content-Type", http.DetectContentType(b))
w.Header().Set(contentType, http.DetectContentType(b))
}
return w.gw.Write(b)
}
// WriteHeader will check if the gzip writer needs to be lazily initiated and
// then pass the code along to the underlying ResponseWriter.
func (w *GzipResponseWriter) WriteHeader(code int) {
if w.gw == nil &&
code != http.StatusNotModified && code != http.StatusNoContent {
w.init()
}
w.ResponseWriter.WriteHeader(code)
}
// init graps a new gzip writer from the gzipWriterPool and writes the correct
// content encoding header.
func (w *GzipResponseWriter) init() {
// Bytes written during ServeHTTP are redirected to this gzip writer
// before being written to the underlying response.
gzw := gzipWriterPools[w.index].Get().(*gzip.Writer)
gzw.Reset(w.ResponseWriter)
w.gw = gzw
w.ResponseWriter.Header().Set(contentEncoding, "gzip")
// if the Content-Length is already set, then calls to Write on gzip
// will fail to set the Content-Length header since its already set
// See: https://github.com/golang/go/issues/14975
w.ResponseWriter.Header().Del(contentLength)
}
// Close will close the gzip.Writer and will put it back in the gzipWriterPool.
func (w *GzipResponseWriter) Close() error {
if w.gw == nil {
return nil
}
err := w.gw.Close()
gzipWriterPools[w.index].Put(w.gw)
return err
}
// Flush flushes the underlying *gzip.Writer and then the underlying
// http.ResponseWriter if it is an http.Flusher. This makes GzipResponseWriter
// an http.Flusher.
func (w GzipResponseWriter) Flush() {
w.gw.Flush()
func (w *GzipResponseWriter) Flush() {
if w.gw != nil {
w.gw.Flush()
}
if fw, ok := w.ResponseWriter.(http.Flusher); ok {
fw.Flush()
}
}
// MustNewGzipLevelHandler behaves just like NewGzipLevelHandler except that in
// an error case it panics rather than returning an error.
func MustNewGzipLevelHandler(level int) func(http.Handler) http.Handler {
wrap, err := NewGzipLevelHandler(level)
if err != nil {
panic(err)
}
return wrap
}
// NewGzipLevelHandler returns a wrapper function (often known as middleware)
// which can be used to wrap an HTTP handler to transparently gzip the response
// body if the client supports it (via the Accept-Encoding header). Responses will
// be encoded at the given gzip compression level. An error will be returned only
// if an invalid gzip compression level is given, so if one can ensure the level
// is valid, the returned error can be safely ignored.
func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) {
if level != gzip.DefaultCompression && (level < gzip.BestSpeed || level > gzip.BestCompression) {
return nil, fmt.Errorf("invalid compression level requested: %d", level)
}
return func(h http.Handler) http.Handler {
index := poolIndex(level)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add(vary, acceptEncoding)
if acceptsGzip(r) {
gw := &GzipResponseWriter{
ResponseWriter: w,
index: index,
}
defer gw.Close()