mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.2 KiB
114 lines
3.2 KiB
// Copyright 2013 Martini Authors |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may |
|
// not use this file except in compliance with the License. You may obtain |
|
// a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
|
// License for the specific language governing permissions and limitations |
|
// under the License. |
|
|
|
package macaron |
|
|
|
import ( |
|
"bufio" |
|
"fmt" |
|
"net" |
|
"net/http" |
|
) |
|
|
|
// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about |
|
// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter |
|
// if the functionality calls for it. |
|
type ResponseWriter interface { |
|
http.ResponseWriter |
|
http.Flusher |
|
// Status returns the status code of the response or 0 if the response has not been written. |
|
Status() int |
|
// Written returns whether or not the ResponseWriter has been written. |
|
Written() bool |
|
// Size returns the size of the response body. |
|
Size() int |
|
// Before allows for a function to be called before the ResponseWriter has been written to. This is |
|
// useful for setting headers or any other operations that must happen before a response has been written. |
|
Before(BeforeFunc) |
|
} |
|
|
|
// BeforeFunc is a function that is called before the ResponseWriter has been written to. |
|
type BeforeFunc func(ResponseWriter) |
|
|
|
// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter |
|
func NewResponseWriter(method string, rw http.ResponseWriter) ResponseWriter { |
|
return &responseWriter{method, rw, 0, 0, nil} |
|
} |
|
|
|
type responseWriter struct { |
|
method string |
|
http.ResponseWriter |
|
status int |
|
size int |
|
beforeFuncs []BeforeFunc |
|
} |
|
|
|
func (rw *responseWriter) WriteHeader(s int) { |
|
rw.callBefore() |
|
rw.ResponseWriter.WriteHeader(s) |
|
rw.status = s |
|
} |
|
|
|
func (rw *responseWriter) Write(b []byte) (size int, err error) { |
|
if !rw.Written() { |
|
// The status will be StatusOK if WriteHeader has not been called yet |
|
rw.WriteHeader(http.StatusOK) |
|
} |
|
if rw.method != "HEAD" { |
|
size, err = rw.ResponseWriter.Write(b) |
|
rw.size += size |
|
} |
|
return size, err |
|
} |
|
|
|
func (rw *responseWriter) Status() int { |
|
return rw.status |
|
} |
|
|
|
func (rw *responseWriter) Size() int { |
|
return rw.size |
|
} |
|
|
|
func (rw *responseWriter) Written() bool { |
|
return rw.status != 0 |
|
} |
|
|
|
func (rw *responseWriter) Before(before BeforeFunc) { |
|
rw.beforeFuncs = append(rw.beforeFuncs, before) |
|
} |
|
|
|
func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { |
|
hijacker, ok := rw.ResponseWriter.(http.Hijacker) |
|
if !ok { |
|
return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface") |
|
} |
|
return hijacker.Hijack() |
|
} |
|
|
|
func (rw *responseWriter) CloseNotify() <-chan bool { |
|
return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() |
|
} |
|
|
|
func (rw *responseWriter) callBefore() { |
|
for i := len(rw.beforeFuncs) - 1; i >= 0; i-- { |
|
rw.beforeFuncs[i](rw) |
|
} |
|
} |
|
|
|
func (rw *responseWriter) Flush() { |
|
flusher, ok := rw.ResponseWriter.(http.Flusher) |
|
if ok { |
|
flusher.Flush() |
|
} |
|
}
|
|
|