返回

Go 语言内置的 Handler

发布时间:2022-12-03 20:23:27 324
# css# html# less# php

在 Go 语言中,有几个内置的 Handler ,这一期就来简单介绍一下这几个 Handler 。


Go 语言内置的 Handler_html

http.NotFoundHandler

Go 语言内置的 Handler_文件系统_02

Go 语言内置的 Handler_文件系统_03

Go 语言内置的 Handler_字符串_04


​NotFoundHandler​​​ 返回一个 handler ,它给每个请求的响应都是 ​​"404 page not found"​​ 。

// NotFoundHandler returns a simple request handler
// that replies to each request with a ``404 page not found'' reply.
func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
// NotFound replies to the request with an HTTP 404 not found error.
func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }

下面是一个例子:

package main

import (
"fmt"
"net/http"
)

func myHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "This is my handler.")
})
}

func main() {
mux := http.NewServeMux()
mux.Handle("/a", http.NotFoundHandler())
mux.Handle("/b", myHandler())
http.ListenAndServe(":8080", mux)
}

运行后在浏览器访问 ​​http://localhost:8080/a​​​ 会响应 ​​"404 page not found"​​​ ;访问 ​​http://localhost:8080/b​​​ 会响应 ​​"This is my handler."​​ 。


Go 语言内置的 Handler_html

http.RedirectHandler

Go 语言内置的 Handler_文件系统_02

Go 语言内置的 Handler_文件系统_03

Go 语言内置的 Handler_字符串_04


​RedirectHandler​​ 是用来跳转的,它有两个参数:

  • 第一个参数是 ​​url​​ 是 string 类型的,表示要跳转到的 URL ;
  • 第二个参数是 ​​code​​ 状态码(3XX),是 int 类型的,常见的有:​​StatusMovedPermanently​​ 、 ​​StatusFound​​ 或 ​​StatusSeeOther​​ 等。

​RedirectHandler​​ 返回的是一个 handler ,它把每个请求使用给定的状态码跳转到指定的 URL 。

// 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}
}
// Redirect to a fixed URL
type redirectHandler struct {
url string
code int
}

Go 语言内置的 Handler_html

http.StripPrefix

Go 语言内置的 Handler_文件系统_02

Go 语言内置的 Handler_文件系统_03

Go 语言内置的 Handler_字符串_04


​StripPrefix​​ 有两个参数:

  • 第一个参数是 ​​prefix​​ 是 string 类型的,表示 URL 将要被移除的字符串前缀;
  • 第二个参数是 ​​h​​ 是一个 handler ,在移除字符串前缀之后,这个 handler 将会接收到请求。

​StripPrefix​​​ 返回一个 handler ,它从请求 URL 中去掉指定的前缀,然后再调用另一个 handler 。如果请求的 URL 与提供的前缀不符,那么响应 ​​"404 page not found"​​ 。

// StripPrefix returns a handler that serves HTTP requests by removing the
// given prefix from the request URL's Path (and RawPath if set) and invoking
// the handler h. StripPrefix handles a request for a path that doesn't begin
// with prefix by replying with an HTTP 404 not found error. The prefix must
// match exactly: if the prefix in the request contains escaped characters
// the reply is also an HTTP 404 not found error.
func StripPrefix(prefix string, h Handler) Handler {
if prefix == "" {
return h
}
return HandlerFunc(func(w ResponseWriter, r *Request) {
p := strings.TrimPrefix(r.URL.Path, prefix)
rp := strings.TrimPrefix(r.URL.RawPath, prefix)
if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) {
r2 := new(Request)
*r2 = *r
r2.URL = new(url.URL)
*r2.URL = *r.URL
r2.URL.Path = p
r2.URL.RawPath = rp
h.ServeHTTP(w, r2)
} else {
NotFound(w, r)
}
})
}

Go 语言内置的 Handler_html

http.TimeoutHandler

Go 语言内置的 Handler_文件系统_02

Go 语言内置的 Handler_文件系统_03

Go 语言内置的 Handler_字符串_04


​TimeoutHandler​​ 有三个参数:

  • 第一个参数是 ​​h​​ ,是将要被修饰的 handler ;
  • 第二个参数是 ​​dt​​ ,是 time.Duration 类型的,是第一个 handler 允许的处理时间;
  • 第三个参数是 ​​msg​​ 是 string 类型的,表示如果超时,那么就把 msg 返回给请求,表示响应时间过长。

它返回一个 handler ,它用来在指定时间内运行传入的 h ,相当于是一个修饰器。

// TimeoutHandler returns a Handler that runs h with the given time limit.
//
// The new Handler calls h.ServeHTTP to handle each request, but if a
// call runs for longer than its time limit, the handler responds with
// a 503 Service Unavailable error and the given message in its body.
// (If msg is empty, a suitable default message will be sent.)
// After such a timeout, writes by h to its ResponseWriter will return
// ErrHandlerTimeout.
//
// TimeoutHandler supports the Pusher interface but does not support
// the Hijacker or Flusher interfaces.
func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {
return &timeoutHandler{
handler: h,
body: msg,
dt: dt,
}
}

Go 语言内置的 Handler_html

http.FileServer

Go 语言内置的 Handler_文件系统_02

Go 语言内置的 Handler_文件系统_03

Go 语言内置的 Handler_字符串_04


​FileServer​​ 返回一个 handler ,使用基于 root 的文件系统来响应请求。

func FileServer(root FileSystem) Handler {
return &fileHandler{root}
}

​root​​ 是一个 FileSystem ,是一个接口,接口里面有一个 Open 方法,该方法有一个 name 参数,该参数是 string 类型的,该方法返回一个 File 文件或者是 error 错误。

// A FileSystem implements access to a collection of named files.
// The elements in a file path are separated by slash ('/', U+002F)
// characters, regardless of host operating system convention.
// See the FileServer function to convert a FileSystem to a Handler.
//
// This interface predates the fs.FS interface, which can be used instead:
// the FS adapter function converts an fs.FS to a FileSystem.
type FileSystem interface {
Open(name string) (File, error)
}

使用时需要用到操作系统的文件系统,还需要委托给:

type Dir string

Dir 也实现了 Open 接口。

// Open implements FileSystem using os.Open, opening files for reading rooted
// and relative to the directory d.
func (d Dir) Open(name string) (File, error) {
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) {
return nil, errors.New("http: invalid character in file path")
}
dir := string(d)
if dir == "" {
dir = "."
}
fullName := filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))
f, err := os.Open(fullName)
if err != nil {
return nil, mapDirOpenError(err, fullName)
}
return f, nil
}

下面是一个例子,我们在 main 目录下新建 wwwroot 目录,在此目录下存放网站的 html 以及相关的 css 和 js 文件,我们的目的是要通过浏览器访问目录下 index.html 文件:

Go 语言内置的 Handler_html_21


package main

import "net/http"

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 第三个参数是想要得到的文件的名字 要加前缀
http.ServeFile(w, r, "main/wwwroot" + r.URL.Path)
})
http.ListenAndServe(":8080", nil)
}

运行上面的程序,通过浏览器访问 ​​http://localhost:8080​​ 就能访问 main/wwwroot 目录下的 index.html 文件,并能加载相关的样式文件。

当然,我们能简化上面的程序:

package main

import "net/http"

func main() {
http.ListenAndServe(":8080", http.FileServer(http.Dir("main/wwwroot")))
}

运行这段代码同样会得到相同的结果。




特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
Go 语言处理 Web 请求 2022-12-03 19:55:16