request response

Request 结构

组成:

  • URL字段
  • Header字段
  • 空行
  • Body字段
  • Form字段、postform字段,multipartForm字段

请求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
	RawPath    string // encoded path hint (Go 1.5 and later only; 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 '#'
}

URL格式一般为
scheme://[userinfo@]host/path[?query][#fragment]

http://www.example.com/post?id=123&thread_id=456

id=123&thread_id=456 ==》 RawQuery字段被设置

request Header

package main

import (
	"fmt"
	"net/http"
)

func headers(w http.ResponseWriter, r *http.Request) {
	h := r.Header // 所有请求头
	
	// 获取某个请求头
	// h := r.Header.Get("User-Agent")

	fmt.Fprintln(w, h)

}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}
	http.HandleFunc("/headers", headers)
	server.ListenAndServe()
}

request Body

package main

import (
	"fmt"
	"net/http"
)

func body(w http.ResponseWriter, r *http.Request) {
	// 读取Body字节长度
	len := r.ContentLength

	// 创建一个字节slice,来存放Body
	body := make([]byte, len)
	r.Body.Read(body)
	fmt.Println(w, string(body))

}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}
	http.HandleFunc("/body", body)
	server.ListenAndServe()
}

Form

// GET
package main

import (
	"fmt"
	"net/http"
)

func process_form(w http.ResponseWriter, r *http.Request) {

	r.ParseForm() // 先对请求继续语法解析,再访问form字段
	fmt.Fprintln(w, r.Form)

}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}
	http.HandleFunc("/form", process_form)
	server.ListenAndServe()
}

/*
http://127.0.0.1:8080/form?h=ewrtgy&dsafdsaf=1234

map[h:[ewrtgy] dsafdsaf:[1234]]
*/

POST form

package main

import (
	"fmt"
	"net/http"
)

func process_form(w http.ResponseWriter, r *http.Request) {

	// r.PostForm() // 先对请求继续语法解析,再访问form字段
	fmt.Fprintln(w, r.PostFormValue("dasfsdfadsf"))

}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}
	http.HandleFunc("/form", process_form)
	server.ListenAndServe()
}

/*
http://127.0.0.1:8080/form

username:saltapi_user
password:sanh123
eauth:pam
dasfsdfadsf:["wedfs","asdfsdfdsf"]


resp:
["wedfs","asdfsdfdsf"]

*/

POST FILE

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

func post_file(w http.ResponseWriter, r *http.Request) {

	r.ParseMultipartForm(1024)

	// 取出文件头
	fileHeader := r.MultipartForm.File["uploaded"][0]
	// fmt.Println(fileHeader)
	// &{client.sql map[Content-Disposition:[form-data; name="uploaded"; filename="client.sql"] Content-Type:[application/octet-stream]] [] C:UsersHOURU~1AppDataLocalTempmultipart-357262171}

	// 通过文件头来打开文件
	file, err := fileHeader.Open()
	if err == nil {
		data, err := ioutil.ReadAll(file)
		if err == nil {
			fmt.Fprintln(w, string(data))
		}
	}

}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}
	http.HandleFunc("/post_file", post_file)
	server.ListenAndServe()
}

  • 方法2
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

func post_file(w http.ResponseWriter, r *http.Request) {
	
	// FormFile 返回的是文件和文件头作为结果, 使用FormFile后不需要手动调用ParseMultipartForm方法
	file, _, err := r.FormFile("uploaded") 
	if err == nil {
		data, err := ioutil.ReadAll(file)
		if err == nil {
			fmt.Fprintln(w, string(data))
		}

	}
}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}
	http.HandleFunc("/post_file", post_file)
	server.ListenAndServe()
}

response

ResponseWriter是一个接口,处理器可通过这个接口创建HTTP response,ResponseWriter会在创建响应时会用到http.response结构

为何ServerHttp为什么要接收ResponseWriter接口和Request指针作为参数,原因是为了让服务器可以觉察到处理器对Request结构的修改,我们必须引用(pass by reference)而不是传值(pass by value)的方式传递Request结构, 源码中ResponseWriter 、Request都是传引用(指针)而不是值

ResponseWriter拥有以下接口:

  • Write
  • WriteHeader
  • Header

Write 接收一个字节数组作为参数,并将数组中的字节写入Http响应的主体中.

package main

import "net/http"

func writeExample(w http.ResponseWriter, r *http.Request) {

	str := `<html>
<head><title>Go Web Programming</title></head>
<body><h1>Hello World</h1></body>
</html>`

	//  通过Write方法将一段HTML字符串写入Http响应的body中, 没有设置Content-Type类型,
	// Write会自动检测并设置正确的类型
	w.Write([]byte(str))

	/*
	   WriteHeader 并不可以设置响应的头首部;
	   Header方法才可以;
	   WriteHeader方法接收一个代表HTTP响应状态码(int 类型)作为参数作为HTTP响应的状态码;
	   再调用这个方法后,用户可以继续对ResponseWrite进行写入,但是不能对响应头的首部做任何写入操作;
	   如果用户在调用Write方法之前没有执行过WriteHeader方法,程序会默认使用200 OK 作为响应作为响应的状态码

	*/

	// WriteHeader
	/*
		WriteHeader 可以自定义 返回 501 Not Implemented
	*/

}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}
	http.HandleFunc("/write", writeExample)
	server.ListenAndServe()
}

自定义返回状态码

package main

import (
	"fmt"
	"net/http"
)

func writeExample(w http.ResponseWriter, r *http.Request) {

	str := `<html>
<head><title>Go Web Programming</title></head>
<body><h1>Hello World</h1></body>
</html>`

	//  通过Write方法将一段HTML字符串写入Http响应的body中, 没有设置Content-Type类型,
	// Write会自动检测并设置正确的类型
	w.Write([]byte(str))
}

func write_Example_HeaderExample(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(501)
	fmt.Fprintln(w, "没有服务,请尝试使用请求其他URL")
}

func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}

	http.HandleFunc("/write", writeExample)
	http.HandleFunc("/write_header", write_Example_HeaderExample)

	server.ListenAndServe()
}

302重定向

package main

import (
	"fmt"
	"net/http"
)

/*func writeExample(w http.ResponseWriter, r *http.Request) {

	str := `<html>
<head><title>Go Web Programming</title></head>
<body><h1>Hello World</h1></body>
</html>`

	w.Write([]byte(str))
}

func write_Example_HeaderExample(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(501)
	fmt.Fprintln(w, "没有服务,请尝试使用请求其他URL")
}*/

func redirect_header(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Location", "http://httpbin.org/")
	w.WriteHeader(302)
}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}

	//http.HandleFunc("/write", writeExample)
	//http.HandleFunc("/write_header", write_Example_HeaderExample)
	http.HandleFunc("/redirect", redirect_header)

	server.ListenAndServe()
}

json

package main

import (
	"encoding/json"

	"net/http"
)

func redirect_header(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Location", "http://httpbin.org/")
	w.WriteHeader(302)
}

type Post_info struct {
	User    string
	Threads []string
}

func jsonExample(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "application/json")
	post := &Post_info{
		User:    "张三",
		Threads: []string{"一", "二"},
	}
	json, _ := json.Marshal(post)
	w.Write(json)
}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}

	http.HandleFunc("/redirect", redirect_header)
	http.HandleFunc("/json", jsonExample)

	server.ListenAndServe()
}

cookie cookie是存储在客户端、体积较小的信息,信息最初都是由服务器通过HTTP响应报文头设置。每当客户端请求时cookie会随着请求一同发送到服务器; cookie设计本意是克服http是无状态性,虽不是唯一的方法,但是是最常用的方法之一,比如广告用户行为.....

cookie种类有很多, 大致分为会话cookie和持久cookie两种类型,其他cookie通常是持久cookie的变种.

cookie在go语言里的使用Cookie结构表示

type Cookie struct {
	Name  string
	Value string

	Path       string    // optional
	Domain     string    // optional
	Expires    time.Time // optional
	RawExpires string    // for reading cookies only

	// MaxAge=0 means no 'Max-Age' attribute specified.
	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
	// MaxAge>0 means Max-Age attribute present and given in seconds
	MaxAge   int
	Secure   bool
	HttpOnly bool
	Raw      string
	Unparsed []string // Raw text of unparsed attribute-value pairs
}

/*
Expires  字段没有设置则被称为临时cookie,浏览器被关闭时自动清除

Expires 明确指明cookie何时过期,
MaxAge  指明cookie在被浏览器创建出来以后能够存活多少秒

两种不同的机制与浏览器设置有关,与语言无关

*/

设置cookie

方法1

package main

import (
	"net/http"
)

func set_cookie(w http.ResponseWriter, r *http.Request) {
	c1 := http.Cookie{
		Name:     "youname",
		Value:    "centos 111 go web",
		HttpOnly: true,
	}
	c2 := http.Cookie{
		Name:     "what",
		Value:    "some1 2222",
		HttpOnly: true,
	}
	w.Header().Set("Set-Cookie", c1.String())
	w.Header().Set("Set-Cookie", c2.String())

}
func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}

	http.HandleFunc("/setcookie", set_cookie)

	server.ListenAndServe()
}

方法2 http.SetCookie

package main

import (
	"net/http"
)

func set_cookie(w http.ResponseWriter, r *http.Request) {
	c1 := http.Cookie{
		Name:     "youname",
		Value:    "centos 111 go web",
		HttpOnly: true,
	}
	c2 := http.Cookie{
		Name:     "what",
		Value:    "some1 2222",
		HttpOnly: true,
	}
	w.Header().Set("Set-Cookie", c1.String())
	w.Header().Set("Set-Cookie", c2.String())

}

func set_cookie1(w http.ResponseWriter, r *http.Request) {
	c1 := http.Cookie{
		Name:     "youname",
		Value:    "centos 111 go web",
		HttpOnly: true,
	}
	c2 := http.Cookie{
		Name:     "what",
		Value:    "some1 2222",
		HttpOnly: true,
	}
	http.SetCookie(w, &c1) // SetCookie使用的是指针,而不是cookie本身
	http.SetCookie(w, &c2)
}

func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}

	http.HandleFunc("/setcookie", set_cookie)
	http.HandleFunc("/setcookie1", set_cookie1)

	server.ListenAndServe()
}

  • 获取cookie
package main

import (
	"fmt"
	"net/http"
)

func set_cookie1(w http.ResponseWriter, r *http.Request) {
	c1 := http.Cookie{
		Name:     "youname",
		Value:    "centos 111 go web",
		HttpOnly: true,
	}
	c2 := http.Cookie{
		Name:     "what",
		Value:    "some1 2222",
		HttpOnly: true,
	}
	http.SetCookie(w, &c1)
	http.SetCookie(w, &c2)
}

func get_cooke(w http.ResponseWriter, r *http.Request) {
	h := r.Header["Cookie"]
	fmt.Fprintln(w, h)
}

func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}

	http.HandleFunc("/setcookie1", set_cookie1)
	http.HandleFunc("/get_cooke", get_cooke)

	server.ListenAndServe()
}
  • 方法2
package main

import (
	"fmt"
	"net/http"
)

func set_cookie1(w http.ResponseWriter, r *http.Request) {
	c1 := http.Cookie{
		Name:     "youname",
		Value:    "centos 111 go web",
		HttpOnly: true,
	}
	c2 := http.Cookie{
		Name:     "what",
		Value:    "some1 2222",
		HttpOnly: true,
	}
	http.SetCookie(w, &c1)
	http.SetCookie(w, &c2)
}

func get_cooke(w http.ResponseWriter, r *http.Request) {
	h := r.Header["Cookie"]
	fmt.Fprintln(w, h)
}

func get_cooke2(w http.ResponseWriter, r *http.Request) {

	//  request 提供了Cookie方法
	c1, err := r.Cookie("youname")
	if err != nil {
		fmt.Fprintln(w, "Cannot get the first cookie")
	}
	cs := r.Cookies()

	fmt.Fprintln(w, c1)
	fmt.Fprintln(w, cs)
}

func main() {
	server := http.Server{Addr: "127.0.0.1:8080"}

	http.HandleFunc("/setcookie1", set_cookie1)
	http.HandleFunc("/get_cooke", get_cooke)

	http.HandleFunc("/get_cooke2", get_cooke2)

	server.ListenAndServe()
}

  • 消息闪现
package main

import (
	"encoding/base64"
	"fmt"
	"net/http"
	"time"
)

func setMessage(w http.ResponseWriter, r *http.Request) {
	msg := []byte("Hello world! 世界")
	c := http.Cookie{
		Name:  "flash_message",
		Value: base64.URLEncoding.EncodeToString(msg), // base64解析是去除空格特殊字符,符合URL编码要求
	}
	http.SetCookie(w, &c)
}
func showMessage(w http.ResponseWriter, r *http.Request) {
	c, err := r.Cookie("flash_message")
	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), // 设置时间为过去的时间浏览器会自动清除cookie
		}
		http.SetCookie(w, &rc)
		val, _ := base64.URLEncoding.DecodeString(c.Value)
		fmt.Fprintln(w, string(val))
	}
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/set_message", setMessage)
	http.HandleFunc("/show_message", showMessage)
	server.ListenAndServe()

}
原文地址:https://www.cnblogs.com/zrdpy/p/8615641.html