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:\Users\ZHOURU~1\AppData\Local\Temp\multipart-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
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()
}