打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Go 语言内置的 Handler

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

http.NotFoundHandler

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."

http.RedirectHandler

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

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

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
}


http.StripPrefix

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)
  }
 })
}


http.TimeoutHandler

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,
 }
}


http.FileServer

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 文件:

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")))
}

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

👇希望对你有帮助,期待你的关注👇

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
GOLANG 中HTTP包默认路由匹配规则阅读笔记
Go语言HTTP Server源码分析
java.net.SocketException: socket failed: EACCES (Permission denied) 异常
go的R方法的使用
gin 源码阅读(1) - gin 与 net/http 的关系
Android开源项目xUtils HttpUtils模块分析
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服