github.com/gogf/gf/v2@v2.7.4/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/gogf/gf. 6 // 7 8 package ghttp 9 10 import ( 11 "fmt" 12 "io" 13 "net/http" 14 "net/url" 15 "time" 16 17 "github.com/gogf/gf/v2/net/ghttp/internal/response" 18 "github.com/gogf/gf/v2/net/gtrace" 19 "github.com/gogf/gf/v2/os/gfile" 20 "github.com/gogf/gf/v2/os/gres" 21 ) 22 23 // Response is the http response manager. 24 // Note that it implements the http.ResponseWriter interface with buffering feature. 25 type Response struct { 26 *response.BufferWriter // Underlying ResponseWriter. 27 Server *Server // Parent server. 28 Request *Request // According request. 29 } 30 31 // newResponse creates and returns a new Response object. 32 func newResponse(s *Server, w http.ResponseWriter) *Response { 33 r := &Response{ 34 Server: s, 35 BufferWriter: response.NewBufferWriter(w), 36 } 37 return r 38 } 39 40 // ServeFile serves the file to the response. 41 func (r *Response) ServeFile(path string, allowIndex ...bool) { 42 var ( 43 serveFile *staticFile 44 ) 45 if file := gres.Get(path); file != nil { 46 serveFile = &staticFile{ 47 File: file, 48 IsDir: file.FileInfo().IsDir(), 49 } 50 } else { 51 path, _ = gfile.Search(path) 52 if path == "" { 53 r.WriteStatus(http.StatusNotFound) 54 return 55 } 56 serveFile = &staticFile{Path: path} 57 } 58 r.Server.serveFile(r.Request, serveFile, allowIndex...) 59 } 60 61 // ServeFileDownload serves file downloading to the response. 62 func (r *Response) ServeFileDownload(path string, name ...string) { 63 var ( 64 serveFile *staticFile 65 downloadName = "" 66 ) 67 68 if len(name) > 0 { 69 downloadName = name[0] 70 } 71 if file := gres.Get(path); file != nil { 72 serveFile = &staticFile{ 73 File: file, 74 IsDir: file.FileInfo().IsDir(), 75 } 76 if downloadName == "" { 77 downloadName = gfile.Basename(file.Name()) 78 } 79 } else { 80 path, _ = gfile.Search(path) 81 if path == "" { 82 r.WriteStatus(http.StatusNotFound) 83 return 84 } 85 serveFile = &staticFile{Path: path} 86 if downloadName == "" { 87 downloadName = gfile.Basename(path) 88 } 89 } 90 r.Header().Set("Content-Type", "application/force-download") 91 r.Header().Set("Accept-Ranges", "bytes") 92 r.Header().Set("Content-Disposition", fmt.Sprintf(`attachment;filename=%s`, url.QueryEscape(downloadName))) 93 r.Header().Set("Access-Control-Expose-Headers", "Content-Disposition") 94 r.Server.serveFile(r.Request, serveFile) 95 } 96 97 // RedirectTo redirects the client to another location. 98 // The optional parameter `code` specifies the http status code for redirecting, 99 // which commonly can be 301 or 302. It's 302 in default. 100 func (r *Response) RedirectTo(location string, code ...int) { 101 r.Header().Set("Location", location) 102 if len(code) > 0 { 103 r.WriteHeader(code[0]) 104 } else { 105 r.WriteHeader(http.StatusFound) 106 } 107 r.Request.Exit() 108 } 109 110 // RedirectBack redirects the client back to referer. 111 // The optional parameter `code` specifies the http status code for redirecting, 112 // which commonly can be 301 or 302. It's 302 in default. 113 func (r *Response) RedirectBack(code ...int) { 114 r.RedirectTo(r.Request.GetReferer(), code...) 115 } 116 117 // ServeContent replies to the request using the content in the 118 // provided ReadSeeker. The main benefit of ServeContent over io.Copy 119 // is that it handles Range requests properly, sets the MIME type, and 120 // handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since, 121 // and If-Range requests. 122 // 123 // See http.ServeContent 124 func (r *Response) ServeContent(name string, modTime time.Time, content io.ReadSeeker) { 125 http.ServeContent(r.RawWriter(), r.Request.Request, name, modTime, content) 126 } 127 128 // Flush outputs the buffer content to the client and clears the buffer. 129 func (r *Response) Flush() { 130 r.Header().Set(responseHeaderTraceID, gtrace.GetTraceID(r.Request.Context())) 131 if r.Server.config.ServerAgent != "" { 132 r.Header().Set("Server", r.Server.config.ServerAgent) 133 } 134 r.BufferWriter.Flush() 135 }