zoukankan      html  css  js  c++  java
  • Go Web编程 第四章--处理请求

    请求和响应

    Request结构

    • URL字段
    • Header字段
    • Body字段
    • Form, PostForm, MultipartForm字段

    在处理器函数中,我们可以通过Request获取各个字段的详细信息

    func get_request_value(w *http.ResponseWriter, r *http.Request) {
        h := r.Header
        brower := r.Header.Get("User-Agent")
        fme.Fprintln(w, h)
    
        body := make([]byte, r.ContentLength)
        r.Body.Read(body)
        fmt.Fprintln(w, string(body))
    }
    

    Go与HTML表单

    用户在表单中输入的数据会以键值对的形式记录在请求的主体中,其中表单中的enctype属性决定了以何种形式发送键值对。默认属性值为application/x-www-form-urlencoded,这个属性会把表单中的数据编码一个连续的长查询字符串,另一种编码方式为multipart/form-data,表单中的数据会被转换为一条MIME报文,每个键值对都构成了这个报文的一部分。简单来说,当表单只需要传送简单数据时,默认编码更加简单,高效;而当表单需要传输大量数据(如文件)时,使用后一种编码方式会更好。有些时候,用户可以通过Base64编码,以文本方式传送二进制数据。

    使用Request结构获取表单数据的一般步骤是:

    1. 调用ParseForm或者ParseMultipartForm方法进行语法分析
    2. 访问Form, PostForm, MultipartForm等字段获取数据
    func get_form_data1(w http.ResponseWriter, r *http.Request) {
        r.ParseForm()
        fmt.Fprintln(w, r.Form)
        // PostForm字段只支持默认编码,并且只返回表单值,不返回URL查询值
        fmt.Fprintln(w, r.PostForm)
    }
    

    当使用multipart/form-data编码时,表单数据会被存储到MultipartForm字段中

    func get_form_data2(w http.ResponseWriter, r *http.Request) {
        r.ParseMultipartForm(1024)
        fmt.Fprintln(w, r.MultipartForm)
    }
    

    我们也可以使用FormValue或者PostFormValue快速获取表单值,也两个方法会自动调用ParseForm或者ParseMultipartForm方法,其中PostFormValue只会返回表单键值对而不会返回URL键值对

    使用FormFile方法可以快速的获取被上传的文件

    func process(w http.ResponseWriter, r *http.Request) {
        file, _, err := r.FormFile("upload")
        if err == nil {
            data, err := ioutil.ReadAll(file)
            if err == nil {
                fmt.Fprintln(w, string(data))
            }
        }
    }
    

    ResponseWriter

    • Write 接收一个字节数组,并写入到HTTP响应主体中
    • WriteHeader 改变HTTP响应状态码
    • Header 修改HTTP响应首部
    package main
    
    import (
        json2 "encoding/json"
        "fmt"
        "net/http"
    )
    
    type Post struct {
        User string
        Threads []string
    }
    
    func writeExample(w http.ResponseWriter, r *http.Request) {
        str := `<html>
                <head><title>Go</title></head>
                <body><h1>Hello world</h1></body>
                </html>`
        w.Write([]byte(str))
    }
    
    func writeHeaderExample(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(501)
        fmt.Fprintln(w, "No such service, try next door")
    }
    
    func headerExample(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Location", "http://baidu.com")
        w.WriteHeader(302)
    }
    
    func jsonExample(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        post := &Post{
            User: "authetic",
            Threads: []string{"first", "second"},
        }
        json, _ := json2.Marshal(post)
        w.Write(json)
    }
    
    func main() {
        server := http.Server{
            Addr: "127.0.0.1:8080",
        }
        http.HandleFunc("/write", writeExample)
        http.HandleFunc("/writeheader", writeHeaderExample)
        http.HandleFunc("/redirect", headerExample)
        http.HandleFunc("/json", jsonExample)
        server.ListenAndServe()
    }
    
    

    Go与cookie

    没有设置Expires字段的通常被成为会话cookie,浏览器关闭或刷新cookie就会消失,设置了Expires字段的通常被称为持久cookie,在过期时间之前会一直存在。

    func set_cookie(w http.ResponseWriter, r *http.Request) {
        c1 := http.Cookie{
            Name: "first_cookie",
            Value: "Go Web",
            HttpOnly: true,
        }
        c2 := http.Cookie{
            Name: "second_cookie",
            Value: "Go Web",
            HttpOnly: true,
        }
        
        http.SetCookie(w, &c1)
        http.SetCookie(w, &c2)
    }
    
    func get_cookie(w http.ResponseWriter, r *http.Request) {
        // h := r.Header["Cookie"]
        cl, err := r.Cookie("first_cookie")
        if err != nil {
            fmt.Fprintln(w, "Something wrong")
        }
        cs := r.Cookies()
        fmt.Fprintln(w, cl)
        fmt.Fprintln(w, cs)
    }
    

    cookie实现闪现消息

    func setMessage(w http.ResponseWriter, r *http.Request) {
        msg := []byte("Hello Go")
        c := http.Cookie{
            Name: "flash",
            Value: base64.URLEncoding.EncodeToString(msg),
        }
        http.SetCookie(w, &c)
    }
    
    func showMessage(w http.ResponseWriter, r *http.Request) {
        c, err := r.Cookie("flash")
        if err != nil {
            if err == http.ErrNoCookie {
                fmt.Fprintln(w, "No message found")
            }
        } else {
            rc := http.Cookie{
                Name: "flash",
                MaxAge: -1,
                Expires: time.Unix(1, 0),
            }
            http.SetCookie(w, &rc)
            val, _ := base64.URLEncoding.DecodeString(c.Value)
            fmt.Fprintln(w, string(val))
        }
    }
    
  • 相关阅读:
    js字符串拼接 ·${}·
    [转]CRLF Injection
    域渗透-GPP(组策略)利用
    AS-REPRoasting
    域用户名枚举
    我理解的HTTP请求走私(HTTP Request Smuggling)
    NFS未授权访问
    Hessian反序列化RCE漏洞
    CVE-2020-15778 Openssh命令注入漏洞复现
    在非域内机器上运行harphound
  • 原文地址:https://www.cnblogs.com/authetic/p/10199449.html
Copyright © 2011-2022 走看看