Beispiel #1
0
// errorPage serves a static error page to w according to the status
// code. If there is an error serving the error page, a plaintext error
// message is written instead, and the extra error is logged.
func (h ErrorHandler) errorPage(w http.ResponseWriter, r *http.Request, code int) {
	// See if an error page for this status code was specified
	if pagePath, ok := h.ErrorPages[code]; ok {
		// Try to open it
		errorPage, err := os.Open(pagePath)
		if err != nil {
			// An additional error handling an error... <insert grumpy cat here>
			h.Log.Printf("%s [NOTICE %d %s] could not load error page: %v",
				time.Now().Format(timeFormat), code, r.URL.String(), err)
			httpserver.DefaultErrorFunc(w, r, code)
			return
		}
		defer errorPage.Close()

		// Copy the page body into the response
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		w.WriteHeader(code)
		_, err = io.Copy(w, errorPage)

		if err != nil {
			// Epic fail... sigh.
			h.Log.Printf("%s [NOTICE %d %s] could not respond with %s: %v",
				time.Now().Format(timeFormat), code, r.URL.String(), pagePath, err)
			httpserver.DefaultErrorFunc(w, r, code)
		}

		return
	}

	// Default error response
	httpserver.DefaultErrorFunc(w, r, code)
}
Beispiel #2
0
// ServeHTTP serves a gzipped response if the client supports it.
func (g Gzip) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
		return g.Next.ServeHTTP(w, r)
	}
outer:
	for _, c := range g.Configs {

		// Check request filters to determine if gzipping is permitted for this request
		for _, filter := range c.RequestFilters {
			if !filter.ShouldCompress(r) {
				continue outer
			}
		}

		// Delete this header so gzipping is not repeated later in the chain
		r.Header.Del("Accept-Encoding")

		// gzipWriter modifies underlying writer at init,
		// use a discard writer instead to leave ResponseWriter in
		// original form.
		gzipWriter, err := newWriter(c, ioutil.Discard)
		if err != nil {
			// should not happen
			return http.StatusInternalServerError, err
		}
		defer gzipWriter.Close()
		gz := &gzipResponseWriter{Writer: gzipWriter, ResponseWriter: w}

		var rw http.ResponseWriter
		// if no response filter is used
		if len(c.ResponseFilters) == 0 {
			// replace discard writer with ResponseWriter
			gzipWriter.Reset(w)
			rw = gz
		} else {
			// wrap gzip writer with ResponseFilterWriter
			rw = NewResponseFilterWriter(c.ResponseFilters, gz)
		}

		// Any response in forward middleware will now be compressed
		status, err := g.Next.ServeHTTP(rw, r)

		// If there was an error that remained unhandled, we need
		// to send something back before gzipWriter gets closed at
		// the return of this method!
		if status >= 400 {
			httpserver.DefaultErrorFunc(w, r, status)
			return 0, err
		}
		return status, err
	}

	// no matching filter
	return g.Next.ServeHTTP(w, r)
}