| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 http |
| |
| import ( |
| "bufio" |
| "io" |
| "net" |
| "net/http" |
| ) |
| |
| import ( |
| "github.com/apache/dubbo-go-pixiu/pkg/logger" |
| ) |
| |
| const ( |
| noWritten = -1 |
| defaultStatus = http.StatusOK |
| ) |
| |
| // ResponseWriter ... |
| type ResponseWriter interface { |
| http.ResponseWriter |
| http.Hijacker |
| http.Flusher |
| // todo replace it later version |
| // nolint |
| http.CloseNotifier |
| |
| // Returns the HTTP response status code of the current request. |
| Status() int |
| |
| // Returns the number of bytes already written into the response http body. |
| // See Written() |
| Size() int |
| |
| // Writes the string into the response body. |
| WriteString(string) (int, error) |
| |
| // Returns true if the response body was already written. |
| Written() bool |
| |
| // Forces to write the http header (status code + headers). |
| WriteHeaderNow() |
| |
| // get the http.Pusher for server push |
| Pusher() http.Pusher |
| } |
| |
| type responseWriter struct { |
| http.ResponseWriter |
| size int |
| status int |
| } |
| |
| var _ ResponseWriter = &responseWriter{} |
| |
| func (w *responseWriter) reset(writer http.ResponseWriter) { |
| w.ResponseWriter = writer |
| w.size = noWritten |
| w.status = defaultStatus |
| } |
| |
| func (w *responseWriter) WriteHeader(code int) { |
| if code > 0 && w.status != code { |
| if w.Written() { |
| logger.Debugf("[WARNING] Headers were already written. Wanted to override status with %d code with %d", w.status, code) |
| } |
| w.status = code |
| } |
| } |
| |
| func (w *responseWriter) WriteHeaderNow() { |
| if !w.Written() { |
| w.size = 0 |
| w.ResponseWriter.WriteHeader(w.status) |
| } |
| } |
| |
| func (w *responseWriter) Write(data []byte) (n int, err error) { |
| w.WriteHeaderNow() |
| n, err = w.ResponseWriter.Write(data) |
| w.size += n |
| return |
| } |
| |
| func (w *responseWriter) WriteString(s string) (n int, err error) { |
| w.WriteHeaderNow() |
| n, err = io.WriteString(w.ResponseWriter, s) |
| w.size += n |
| return |
| } |
| |
| func (w *responseWriter) Status() int { |
| return w.status |
| } |
| |
| func (w *responseWriter) Size() int { |
| return w.size |
| } |
| |
| func (w *responseWriter) Written() bool { |
| return w.size != noWritten |
| } |
| |
| // Hijack implements the http.Hijacker interface. |
| func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { |
| if w.size < 0 { |
| w.size = 0 |
| } |
| return w.ResponseWriter.(http.Hijacker).Hijack() |
| } |
| |
| // CloseNotify implements the http.CloseNotify interface. |
| // todo replace this later version |
| // nolint |
| func (w *responseWriter) CloseNotify() <-chan bool { |
| return w.ResponseWriter.(http.CloseNotifier).CloseNotify() |
| } |
| |
| // Flush implements the http.Flush interface. |
| func (w *responseWriter) Flush() { |
| w.WriteHeaderNow() |
| w.ResponseWriter.(http.Flusher).Flush() |
| } |
| |
| func (w *responseWriter) Pusher() (pusher http.Pusher) { |
| if pusher, ok := w.ResponseWriter.(http.Pusher); ok { |
| return pusher |
| } |
| return nil |
| } |