Go-HTTP-RedirectHandler

    xiaoxiao2022-06-27  75

    Keywords: HandlerFunc, RedirectHandler, Redirect

    前言

    在Go-http-HandlerFunc()函数中,详细介绍了HandlerFunc,所以本文换个方式来讲:从外往里一层层剥离,即先讲用户层面的API或使用方法,然后再介绍涉及的内部实现细节。

    RedirectHandler实现代码

    func Redirect(w ResponseWriter, r *Request, urlStr string, code int) { // Skipped now ... } // Redirect to a fixed URL type redirectHandler struct { url string code int } func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) { Redirect(w, r, rh.url, rh.code) } // RedirectHandler returns a request handler that redirects // each request it receives to the given url using the given // status code. // // The provided code should be in the 3xx range and is usually // StatusMovedPermanently, StatusFound or StatusSeeOther. func RedirectHandler(url string, code int) Handler { return &redirectHandler{url, code} }

    惯用法

    用户可以看到的接口就是:

    func RedirectHandler(url string, code int) Handler

    示例

    TODO 待补充

    type redirectHandler

    上面的源代码中,给出了type redirectHandler的定义。——redirectHandler也是Handler接口的一个实现。

    Redirect()

    redirectHandler具体类用到了Redirect()函数,源代码如下:

    // Redirect replies to the request with a redirect to url, // which may be a path relative to the request path. // // The provided code should be in the 3xx range and is usually // StatusMovedPermanently, StatusFound or StatusSeeOther. func Redirect(w ResponseWriter, r *Request, urlStr string, code int) { if u, err := url.Parse(urlStr); err == nil { // If url was relative, make absolute by // combining with request path. // The browser would probably do this for us, // but doing it ourselves is more reliable. // NOTE(rsc): RFC 2616 says that the Location // line must be an absolute URI, like // "http://www.google.com/redirect/", // not a path like "/redirect/". // Unfortunately, we don't know what to // put in the host name section to get the // client to connect to us again, so we can't // know the right absolute URI to send back. // Because of this problem, no one pays attention // to the RFC; they all send back just a new path. // So do we. if u.Scheme == "" && u.Host == "" { oldpath := r.URL.Path if oldpath == "" { // should not happen, but avoid a crash if it does oldpath = "/" } // no leading http://server if urlStr == "" || urlStr[0] != '/' { // make relative path absolute olddir, _ := path.Split(oldpath) urlStr = olddir + urlStr } var query string if i := strings.Index(urlStr, "?"); i != -1 { urlStr, query = urlStr[:i], urlStr[i:] } // clean up but preserve trailing slash trailing := strings.HasSuffix(urlStr, "/") urlStr = path.Clean(urlStr) if trailing && !strings.HasSuffix(urlStr, "/") { urlStr += "/" } urlStr += query } } w.Header().Set("Location", urlStr) w.WriteHeader(code) // RFC 2616 recommends that a short note "SHOULD" be included in the // response because older user agents may not understand 301/307. // Shouldn't send the response for POST or HEAD; that leaves GET. if r.Method == "GET" { note := "<a href=\"" + htmlEscape(urlStr) + "\">" + statusText[code] + "</a>.\n" fmt.Fprintln(w, note) } } var htmlReplacer = strings.NewReplacer( "&", "&", "<", "<", ">", ">", // """ is shorter than """. `"`, """, // "'" is shorter than "'" and apos was not in HTML until HTML5. "'", "'", ) func htmlEscape(s string) string { return htmlReplacer.Replace(s) }

    待详细解释

    转载请注明原文地址: https://ju.6miu.com/read-1124087.html

    最新回复(0)