美文网首页
Go Web开发四:处理请求

Go Web开发四:处理请求

作者: 狂奔的胖蜗牛 | 来源:发表于2018-06-26 21:44 被阅读106次

    1.HTTP报文结构

    HTTP分为请求和响应类型,都具有相同的结构:
    1.请求行或者响应行
    2.0个或者多个首部
    3.一个空行
    4.一个可选的报文主体

    1.1Request结构

    Request结构表示一个客户端发送的HTTP请求报文,该结构包含了报文经过语法分析后较为重要的信息。

    组成:
    1.URL字段
    2.Header字段
    3.Body字段
    4.Form字段
    5.PostForm字段
    6.MultipartForm字段

    通过该结构,可以对请求报文中的cookie,url代理等进行访问。

    1.1.1URL字段

    表示请求中包含的URL,该字段是一个指向url.URL结构的指针。定义如下:

    type URL struct {
        Scheme     string
        Opaque     string    // encoded opaque data
        User       *Userinfo // username and password information
        Host       string    // host or host:port
        Path       string    // path (relative paths may omit leading slash)
        RawPath    string    // encoded path hint (see EscapedPath method)
        ForceQuery bool      // append a query ('?') even if RawQuery is empty
        RawQuery   string    // encoded query values, without '?'
        Fragment   string    // fragment for references, without '#'
    }
    

    1.1.2Header字段

    请求和响应的首部都使用Header类型描述。

    package main
    
    import (
        "net/http"
        "fmt"
    )
    
    func main() {
        server := http.Server{
            Addr: "127.0.0.1:8080",
        }
        http.HandleFunc("/headers", headers)
        server.ListenAndServe()
    }
    
    func headers(w http.ResponseWriter, r *http.Request) {
        h := r.Header
        fmt.Fprintln(w, h)
    }
    
    

    代码中的r.Header即把请求首部读取出来,并写入response返回给客户端。

    可以使用指定键获得Header中的值,如:

    //获得字符串切片
    h := r.Header["Accept-Encoding"]
    //获得字符串,使用逗号分隔开
    h := r.Header.Get("Accept-Encoding")
    

    1.1.3Body字段

    请求和响应的主体都由Request结构的Body字段表示,该字段是一个io.ReadCloser接口。

    使用Read方法读取主体的内容:

    func main() {
        server := http.Server{
            Addr: "localhost:8080",
        }
        http.HandleFunc("/body", body)
        server.ListenAndServe()
    }
    
    func body(w http.ResponseWriter, r *http.Request) {
        len := r.ContentLength//获取主体数据的字节长度
        body := make([]byte, len)//根据长度创建出字节数组
        r.Body.Read(body)//将主体数据读取到body中
        fmt.Fprintln(w, string(body))
    }
    

    在终端使用cURL命令即可模拟POST请求

    yuhua$ curl -id "body" localhost:8080/body
    

    输出如下内容:

    HTTP/1.1 200 OK
    Date: Mon, 25 Jun 2018 15:12:11 GMT
    Content-Length: 5
    Content-Type: text/plain; charset=utf-8
    
    body
    

    1.1.4Form字段

    通过调用Request提供的方法,用户可以将URL,主体等数据提取到Form,PostForm,MultipartForm等字段中。下面代码调用了ParseForm方法,访问时,就应该访问相应的Form字段。

    func main() {
        server := http.Server{
            Addr: "localhost:8080",
        }
        http.HandleFunc("/process", process)
        server.ListenAndServe()
    }
    
    func process(w http.ResponseWriter, r *http.Request) {
        r.ParseForm()//对表单进行分析
        fmt.Fprintln(w, r.Form)
    }
    

    编写好html文件,用浏览器打开:

    <html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
        <title>GoWeb</title>
    </head>
    <form action=http://127.0.0.1:8080/process?hello=world&thread=123 method="post" enctype="application/x-www-form-urlencoded">
        <input type="text" name="hello" value="sau"/>
        <input type="text" name="post" value="456"/>
        <input type="submit">
    </form>
    </html>
    

    点击提交后,得到如下结果:

    map[post:[456] hello:[sau world] thread:[123]]
    

    我们发现,使用application/x-www-form-urlencoded格式,最终的Form字段会包含URL与body中的值。

    2.ResponseWrite

    ResponseWrite是一个接口,处理器通过该接口创建HTTP响应。

    该接口有3个方法:
    1.Write
    2.WriteHeader
    3.Header

    2.1Write

    package main
    
    import "net/http"
    
    func main() {
        server := http.Server{
            Addr: "localhost:8080",
        }
        http.HandleFunc("/write", write)
        server.ListenAndServe()
    }
    
    func write(w http.ResponseWriter, r *http.Request) {
        str := `<html><head><title>Go Web</title></head><body><h1>Hello World</h1></body></html>`
        w.Write([]byte(str))
    }
    

    浏览器浏览后:


    屏幕快照 2018-06-26 下午9.23.24.png

    2.2WriteHeader

    将状态码写入返回中。如:你定义一个API,但是没有实现,当客户端访问时,可以返回501。

    package main
    
    import (
        "net/http"
        "fmt"
    )
    
    func main() {
        server := http.Server{
            Addr: "localhost:8080",
        }
        http.HandleFunc("/write", write)
        http.HandleFunc("/writeHeader", writeHeader)
        server.ListenAndServe()
    }
    
    func write(w http.ResponseWriter, r *http.Request) {
        str := `<html><head><title>Go Web</title></head><body><h1>Hello World</h1></body></html>`
        w.Write([]byte(str))
    }
    
    func writeHeader(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(501)//该方法只允许设置一次,不允许多次设置
        fmt.Fprintln(w, "没有实现!")
    }
    

    访问后:


    屏幕快照 2018-06-26 下午9.29.30.png

    2.3Header

    调用Header方法,可以取得一个由首部组成的映射,修改该映射就可以修改首部,修改后的首部被包含在HTTP响应里,并随着响应一同发送至客户端。

    package main
    
    import (
        "net/http"
        "fmt"
    )
    
    func main() {
        server := http.Server{
            Addr: "localhost:8080",
        }
        http.HandleFunc("/write", write)
        http.HandleFunc("/writeHeader", writeHeader)
        http.HandleFunc("/header", header)
        server.ListenAndServe()
    }
    
    func write(w http.ResponseWriter, r *http.Request) {
        str := `<html><head><title>Go Web</title></head><body><h1>Hello World</h1></body></html>`
        w.Write([]byte(str))
    }
    
    func writeHeader(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(501)
        fmt.Fprintln(w, "没有实现!")
    }
    
    func header(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Location", "http://www.baidu.com")
        w.WriteHeader(302)
    }
    

    浏览器打开会自动跳转到百度页面。

    2.4返回JSON

    返回Back结构体JSON。

    package main
    
    import (
        "net/http"
        "fmt"
        json2 "encoding/json"
    )
    
    func main() {
        server := http.Server{
            Addr: "localhost:8080",
        }
        http.HandleFunc("/write", write)
        http.HandleFunc("/writeHeader", writeHeader)
        http.HandleFunc("/header", header)
        http.HandleFunc("/json", jsonBack)
        server.ListenAndServe()
    }
    
    func write(w http.ResponseWriter, r *http.Request) {
        str := `<html><head><title>Go Web</title></head><body><h1>Hello World</h1></body></html>`
        w.Write([]byte(str))
    }
    
    func writeHeader(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(501)
        fmt.Fprintln(w, "没有实现!")
    }
    
    func header(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Location", "http://www.baidu.com")
        w.WriteHeader(302)
    }
    
    type back struct {
        User string
        Threads []string
    }
    
    func jsonBack(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Conten-Type", "application/json")
        back := &back{
            User: "Sau",
            Threads: []string{"first", "second", "third"},
        }
        json, _ :=  json2.Marshal(back)
        w.Write(json)
    }
    

    浏览器浏览后返回:


    屏幕快照 2018-06-26 下午9.43.11.png

    相关文章

      网友评论

          本文标题:Go Web开发四:处理请求

          本文链接:https://www.haomeiwen.com/subject/mpmuyftx.html