github.com/zhongdalu/gf@v1.0.0/g/net/ghttp/ghttp_response.go (about)

     1  // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf.
     6  //
     7  
     8  package ghttp
     9  
    10  import (
    11  	"bytes"
    12  	"fmt"
    13  	"net/http"
    14  	"strconv"
    15  
    16  	"github.com/zhongdalu/gf/g/encoding/gparser"
    17  	"github.com/zhongdalu/gf/g/os/gfile"
    18  	"github.com/zhongdalu/gf/g/util/gconv"
    19  )
    20  
    21  // 服务端请求返回对象。
    22  // 注意该对象并没有实现http.ResponseWriter接口,而是依靠ghttp.ResponseWriter实现。
    23  type Response struct {
    24  	ResponseWriter
    25  	Server  *Server         // 所属Web Server
    26  	Writer  *ResponseWriter // ResponseWriter的别名
    27  	request *Request        // 关联的Request请求对象
    28  }
    29  
    30  // 创建一个ghttp.Response对象指针
    31  func newResponse(s *Server, w http.ResponseWriter) *Response {
    32  	r := &Response{
    33  		Server: s,
    34  		ResponseWriter: ResponseWriter{
    35  			ResponseWriter: w,
    36  			buffer:         bytes.NewBuffer(nil),
    37  		},
    38  	}
    39  	r.Writer = &r.ResponseWriter
    40  	return r
    41  }
    42  
    43  // 返回信息,任何变量自动转换为bytes
    44  func (r *Response) Write(content ...interface{}) {
    45  	if len(content) == 0 {
    46  		return
    47  	}
    48  	for _, v := range content {
    49  		switch value := v.(type) {
    50  		case []byte:
    51  			r.buffer.Write(value)
    52  		case string:
    53  			r.buffer.WriteString(value)
    54  		default:
    55  			r.buffer.WriteString(gconv.String(v))
    56  		}
    57  	}
    58  }
    59  
    60  // 返回信息,支持自定义format格式
    61  func (r *Response) Writef(format string, params ...interface{}) {
    62  	r.Write(fmt.Sprintf(format, params...))
    63  }
    64  
    65  // 返回信息,末尾增加换行标识符"\n"
    66  func (r *Response) Writeln(content ...interface{}) {
    67  	if len(content) == 0 {
    68  		r.Write("\n")
    69  		return
    70  	}
    71  	content = append(content, "\n")
    72  	r.Write(content...)
    73  }
    74  
    75  // 返回信息,末尾增加换行标识符"\n"
    76  func (r *Response) Writefln(format string, params ...interface{}) {
    77  	r.Writeln(fmt.Sprintf(format, params...))
    78  }
    79  
    80  // 返回JSON
    81  func (r *Response) WriteJson(content interface{}) error {
    82  	if b, err := gparser.VarToJson(content); err != nil {
    83  		return err
    84  	} else {
    85  		r.Header().Set("Content-Type", "application/json")
    86  		r.Write(b)
    87  	}
    88  	return nil
    89  }
    90  
    91  // 返回JSONP
    92  func (r *Response) WriteJsonP(content interface{}) error {
    93  	if b, err := gparser.VarToJson(content); err != nil {
    94  		return err
    95  	} else {
    96  		//r.Header().Set("Content-Type", "application/json")
    97  		if callback := r.request.Get("callback"); callback != "" {
    98  			buffer := []byte(callback)
    99  			buffer = append(buffer, byte('('))
   100  			buffer = append(buffer, b...)
   101  			buffer = append(buffer, byte(')'))
   102  			r.Write(buffer)
   103  		} else {
   104  			r.Write(b)
   105  		}
   106  	}
   107  	return nil
   108  }
   109  
   110  // 返回XML
   111  func (r *Response) WriteXml(content interface{}, rootTag ...string) error {
   112  	if b, err := gparser.VarToXml(content, rootTag...); err != nil {
   113  		return err
   114  	} else {
   115  		r.Header().Set("Content-Type", "application/xml")
   116  		r.Write(b)
   117  	}
   118  	return nil
   119  }
   120  
   121  // Deprecated, please use CORSDefault instead.
   122  //
   123  // (已废弃,请使用CORSDefault)允许AJAX跨域访问.
   124  func (r *Response) SetAllowCrossDomainRequest(allowOrigin string, allowMethods string, maxAge ...int) {
   125  	age := 3628800
   126  	if len(maxAge) > 0 {
   127  		age = maxAge[0]
   128  	}
   129  	r.Header().Set("Access-Control-Allow-Origin", allowOrigin)
   130  	r.Header().Set("Access-Control-Allow-Methods", allowMethods)
   131  	r.Header().Set("Access-Control-Max-Age", strconv.Itoa(age))
   132  }
   133  
   134  // 返回HTTP Code状态码
   135  func (r *Response) WriteStatus(status int, content ...interface{}) {
   136  	if r.buffer.Len() == 0 {
   137  		// 状态码注册回调函数处理
   138  		if status != http.StatusOK {
   139  			if f := r.request.Server.getStatusHandler(status, r.request); f != nil {
   140  				r.Server.niceCallFunc(func() {
   141  					f(r.request)
   142  				})
   143  				// 防止多次设置(http: multiple response.WriteHeader calls)
   144  				if r.Status == 0 {
   145  					r.WriteHeader(status)
   146  				}
   147  				return
   148  			}
   149  		}
   150  		if r.Header().Get("Content-Type") == "" {
   151  			r.Header().Set("Content-Type", "text/plain; charset=utf-8")
   152  			//r.Header().Set("X-Content-Type-Options", "nosniff")
   153  		}
   154  		if len(content) > 0 {
   155  			r.Write(content...)
   156  		} else {
   157  			r.Write(http.StatusText(status))
   158  		}
   159  	}
   160  	r.WriteHeader(status)
   161  }
   162  
   163  // 静态文件处理
   164  func (r *Response) ServeFile(path string) {
   165  	// 首先判断是否给定的path已经是一个绝对路径
   166  	path = gfile.RealPath(path)
   167  	if path == "" {
   168  		r.WriteStatus(http.StatusNotFound)
   169  		return
   170  	}
   171  	r.Server.serveFile(r.request, path)
   172  }
   173  
   174  // 静态文件下载处理
   175  func (r *Response) ServeFileDownload(path string, name ...string) {
   176  	// 首先判断是否给定的path已经是一个绝对路径
   177  	path = gfile.RealPath(path)
   178  	if path == "" {
   179  		r.WriteStatus(http.StatusNotFound)
   180  		return
   181  	}
   182  	downloadName := ""
   183  	if len(name) > 0 {
   184  		downloadName = name[0]
   185  	} else {
   186  		downloadName = gfile.Basename(path)
   187  	}
   188  	r.Header().Set("Content-Type", "application/force-download")
   189  	r.Header().Set("Accept-Ranges", "bytes")
   190  	r.Header().Set("Content-Disposition", fmt.Sprintf(`attachment;filename="%s"`, downloadName))
   191  	r.Server.serveFile(r.request, path)
   192  }
   193  
   194  // 返回location标识,引导客户端跳转。
   195  // 注意这里要先把设置的cookie输出,否则会被忽略。
   196  func (r *Response) RedirectTo(location string) {
   197  	r.Header().Set("Location", location)
   198  	r.WriteHeader(http.StatusFound)
   199  	r.request.Exit()
   200  }
   201  
   202  // 返回location标识,引导客户端跳转到来源页面
   203  func (r *Response) RedirectBack() {
   204  	r.RedirectTo(r.request.GetReferer())
   205  }
   206  
   207  // 获取当前缓冲区中的数据
   208  func (r *Response) Buffer() []byte {
   209  	return r.buffer.Bytes()
   210  }
   211  
   212  // 获取当前缓冲区中的数据大小
   213  func (r *Response) BufferLength() int {
   214  	return r.buffer.Len()
   215  }
   216  
   217  // 手动设置缓冲区内容
   218  func (r *Response) SetBuffer(data []byte) {
   219  	r.buffer.Reset()
   220  	r.buffer.Write(data)
   221  }
   222  
   223  // 清空缓冲区内容
   224  func (r *Response) ClearBuffer() {
   225  	r.buffer.Reset()
   226  }
   227  
   228  // Deprecated.
   229  //
   230  // 输出缓冲区数据到客户端.
   231  func (r *Response) OutputBuffer() {
   232  	r.Header().Set("Server", r.Server.config.ServerAgent)
   233  	//r.handleGzip()
   234  	r.Writer.OutputBuffer()
   235  }
   236  
   237  // 输出缓冲区数据到客户端.
   238  func (r *Response) Output() {
   239  	r.Header().Set("Server", r.Server.config.ServerAgent)
   240  	//r.handleGzip()
   241  	r.Writer.OutputBuffer()
   242  }