github.com/wangyougui/gf/v2@v2.6.5/net/ghttp/ghttp_response.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 // 7 8 package ghttp 9 10 import ( 11 "bytes" 12 "fmt" 13 "io" 14 "net/http" 15 "net/url" 16 "time" 17 18 "github.com/wangyougui/gf/v2/net/ghttp/internal/response" 19 "github.com/wangyougui/gf/v2/net/gtrace" 20 "github.com/wangyougui/gf/v2/os/gfile" 21 "github.com/wangyougui/gf/v2/os/gres" 22 ) 23 24 // Response is the http response manager. 25 // Note that it implements the http.ResponseWriter interface with buffering feature. 26 type Response struct { 27 *ResponseWriter // Underlying ResponseWriter. 28 Server *Server // Parent server. 29 Writer *ResponseWriter // Alias of ResponseWriter. 30 Request *Request // According request. 31 } 32 33 // newResponse creates and returns a new Response object. 34 func newResponse(s *Server, w http.ResponseWriter) *Response { 35 r := &Response{ 36 Server: s, 37 ResponseWriter: &ResponseWriter{ 38 writer: response.NewWriter(w), 39 buffer: bytes.NewBuffer(nil), 40 }, 41 } 42 r.Writer = r.ResponseWriter 43 return r 44 } 45 46 // ServeFile serves the file to the response. 47 func (r *Response) ServeFile(path string, allowIndex ...bool) { 48 var ( 49 serveFile *staticFile 50 ) 51 if file := gres.Get(path); file != nil { 52 serveFile = &staticFile{ 53 File: file, 54 IsDir: file.FileInfo().IsDir(), 55 } 56 } else { 57 path, _ = gfile.Search(path) 58 if path == "" { 59 r.WriteStatus(http.StatusNotFound) 60 return 61 } 62 serveFile = &staticFile{Path: path} 63 } 64 r.Server.serveFile(r.Request, serveFile, allowIndex...) 65 } 66 67 // ServeFileDownload serves file downloading to the response. 68 func (r *Response) ServeFileDownload(path string, name ...string) { 69 var ( 70 serveFile *staticFile 71 downloadName = "" 72 ) 73 74 if len(name) > 0 { 75 downloadName = name[0] 76 } 77 if file := gres.Get(path); file != nil { 78 serveFile = &staticFile{ 79 File: file, 80 IsDir: file.FileInfo().IsDir(), 81 } 82 if downloadName == "" { 83 downloadName = gfile.Basename(file.Name()) 84 } 85 } else { 86 path, _ = gfile.Search(path) 87 if path == "" { 88 r.WriteStatus(http.StatusNotFound) 89 return 90 } 91 serveFile = &staticFile{Path: path} 92 if downloadName == "" { 93 downloadName = gfile.Basename(path) 94 } 95 } 96 r.Header().Set("Content-Type", "application/force-download") 97 r.Header().Set("Accept-Ranges", "bytes") 98 r.Header().Set("Content-Disposition", fmt.Sprintf(`attachment;filename=%s`, url.QueryEscape(downloadName))) 99 r.Server.serveFile(r.Request, serveFile) 100 } 101 102 // RedirectTo redirects the client to another location. 103 // The optional parameter `code` specifies the http status code for redirecting, 104 // which commonly can be 301 or 302. It's 302 in default. 105 func (r *Response) RedirectTo(location string, code ...int) { 106 r.Header().Set("Location", location) 107 if len(code) > 0 { 108 r.WriteHeader(code[0]) 109 } else { 110 r.WriteHeader(http.StatusFound) 111 } 112 r.Request.Exit() 113 } 114 115 // RedirectBack redirects the client back to referer. 116 // The optional parameter `code` specifies the http status code for redirecting, 117 // which commonly can be 301 or 302. It's 302 in default. 118 func (r *Response) RedirectBack(code ...int) { 119 r.RedirectTo(r.Request.GetReferer(), code...) 120 } 121 122 // Buffer returns the buffered content as []byte. 123 func (r *Response) Buffer() []byte { 124 return r.buffer.Bytes() 125 } 126 127 // BufferString returns the buffered content as string. 128 func (r *Response) BufferString() string { 129 return r.buffer.String() 130 } 131 132 // BufferLength returns the length of the buffered content. 133 func (r *Response) BufferLength() int { 134 return r.buffer.Len() 135 } 136 137 // SetBuffer overwrites the buffer with `data`. 138 func (r *Response) SetBuffer(data []byte) { 139 r.buffer.Reset() 140 r.buffer.Write(data) 141 } 142 143 // ClearBuffer clears the response buffer. 144 func (r *Response) ClearBuffer() { 145 r.buffer.Reset() 146 } 147 148 // ServeContent replies to the request using the content in the 149 // provided ReadSeeker. The main benefit of ServeContent over io.Copy 150 // is that it handles Range requests properly, sets the MIME type, and 151 // handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since, 152 // and If-Range requests. 153 // 154 // See http.ServeContent 155 func (r *Response) ServeContent(name string, modTime time.Time, content io.ReadSeeker) { 156 http.ServeContent(r.Writer.RawWriter(), r.Request.Request, name, modTime, content) 157 } 158 159 // Flush outputs the buffer content to the client and clears the buffer. 160 func (r *Response) Flush() { 161 r.Header().Set(responseHeaderTraceID, gtrace.GetTraceID(r.Request.Context())) 162 if r.Server.config.ServerAgent != "" { 163 r.Header().Set("Server", r.Server.config.ServerAgent) 164 } 165 r.Writer.Flush() 166 }