1.http请求包
Accept-Encoding:gzip, deflate, br 是否支持流压缩
Accept-Language:zh-CN,zh;q=0.9 浏览器申明自己接收的编码方法
Cache-Control:max-age=0
Connection:keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
Cookie:hibext_instdsigdip=1; hibext_instdsigdipv2=1; _ga=GA1.1.3997200.1517318632; csrftoken=M897uTeIq8mg2TjkJp1fmnifvhHNKoe5SvW50bCbrQVbxNq5PILmvl7UEoFhC5AZ; OUTFOX_SEARCH_USER_ID_NCOO=109431709.18546157; sessionid=903plvwdj8j8a4qf10vammytmkgtkarm; _gid=GA1.1.538902467.1519714828; _gat=1; trdipcktrffcext=1
Host:127.0.0.1:8080 请求的主机
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 客户端(浏览器)相关信息
Request Method:GET
进一步分解如下图:
2.响应报文解析:
HTTP的响应报文也由三部分组成(响应行+响应头+响应体):
①报文协议及版本;
②状态码及状态描述;
③响应报文头,也是由多个属性组成;
④响应报文体,即我们真正要的“干货”。
1.简单http客户端
package main import ( "fmt" "io/ioutil" "net/http" ) func main(){ res,err := http.Get("https://www.baidu.com") if err != nil { fmt.Println("Get err:",err) return } data,err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println("read failed:",err) return } fmt.Println(string(data)) }
运行结果:
<html>
<head>
<script>
location.replace(location.href.replace("https://","http://"));
</script>
</head>
<body>
<noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>
</body>
</html>
2.http服务端
package main import( "fmt" "net/http" ) func hello(w http.ResponseWriter,r *http.Request){ fmt.Fprintf(w,"helloworld") } func main(){ http.HandleFunc("/",hello) err:=http.ListenAndServe(":8080",nil) if err != nil { fmt.Println("http listen failed err:",err) } }
访问:
3.用客户访问自己的httpserver
package main import ( "fmt" "io/ioutil" "net/http" ) func main(){ res,err := http.Get("http://127.0.0.1:8080") if err != nil { fmt.Println("Get err:",err) return } data,err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println("read failed:",err) return } fmt.Println(string(data)) }
访问结果:
4.http常见请求方法
Get Post Put Delete Head
5.head 请求实例:
package main import ( "net/http" "fmt" "io/ioutil" // "strings" ) func test3(){ var url = []string{ "http://www.baidu.com", "http://www.google.com/", "http://taobao.com", } for _,v := range url{ reps,err:= http.Head(v) if err != nil { fmt.Println("Head failed",err) continue } fmt.Println("head sucess:",reps) } } func main(){ test3() } 运行结果如下:
6.http常见状态码
http.StatusContinue = 100
http.StatusOK = 200
http.StatusFound = 302
http.StatusBadRequest = 400
http.StatusUnauthorized =
401
http.StatusForbidden = 403
http.StatusNotFound = 404
http.StatusInternalServerEr
ror = 500
7.表单处理
package main import ( "fmt" "io" "net/http" ) const form =`<html><body><form action="#" method="post" name="bar"> <input type="text" name="user"/> <input type="text" name="pwd"/> <input type="submit" value="Submit"/> </form></body><html>` func SimpleServer(w http.ResponseWriter, r *http.Request){ io.WriteString(w,"<h1>hello,world</h1>") } func FormServer(w http.ResponseWriter, r *http.Request){ w.Header().Set("Content-Type","text/html") //设置响应头内容 w.Header().Set("wang","haijun") switch r.Method{ case "GET": io.WriteString(w,form) //如果是Get请求,则把form表单内容返回去 case "POST": r.ParseForm() //解析表单,获取表单内容 io.WriteString(w,r.Form["user"][0]) //获取表单内容,并返回给浏览器 io.WriteString(w,r.FormValue("user")) //获取表单内容,并返回给浏览器 io.WriteString(w," ") io.WriteString(w,r.Form["pwd"][0]) io.WriteString(w,r.FormValue("pwd")) } } func main(){ http.HandleFunc("/test1", SimpleServer) http.HandleFunc("/test2", FormServer) err :=http.ListenAndServe("0.0.0.0:80",nil) if err != nil { fmt.Println(err) } }
8.http panic处理
package main import ( "fmt" "io" "net/http" ) const form =`<html><body><form action="#" method="post" name="bar"> <input type="text" name="user"/> <input type="text" name="pwd"/> <input type="submit" value="Submit"/> </form></body><html>` func SimpleServer(w http.ResponseWriter, r *http.Request){ var p *int //制造错误 *p = 100 io.WriteString(w,"<h1>hello,world</h1>") } func FormServer(w http.ResponseWriter, r *http.Request){ w.Header().Set("Content-Type","text/html") //设置响应头内容 w.Header().Set("wang","haijun") switch r.Method{ case "GET": io.WriteString(w,form) //如果是Get请求,则把form表单内容返回去 case "POST": r.ParseForm() //解析表单,获取表单内容 io.WriteString(w,r.Form["user"][0]) //获取表单内容,并返回给浏览器 io.WriteString(w,r.FormValue("user")) //获取表单内容,并返回给浏览器 io.WriteString(w," ") io.WriteString(w,r.Form["pwd"][0]) io.WriteString(w,r.FormValue("pwd")) } } func main(){ http.HandleFunc("/test1",SimpleServer) http.HandleFunc("/test2", FormServer) err :=http.ListenAndServe("0.0.0.0:80",nil) if err != nil { fmt.Println(err) } }
上面人为制造了一个错误,但是并没有捕捉,现在go语言已经经过 了处理,服务器不会崩溃,原来如果不捕捉就会崩溃,不过最好是捕捉一下。看没有捕捉的运行结果:
运行服务:
go run .main.go
访问url:127.0.0.1/test1
看服务器报错:
继续访问url:127.0.0.1/test2
test2还可以访问,go内部经过了处理。
自己捕捉错误:
package main import ( "fmt" "io" "net/http" ) const form =`<html><body><form action="#" method="post" name="bar"> <input type="text" name="user"/> <input type="text" name="pwd"/> <input type="submit" value="Submit"/> </form></body><html>` func SimpleServer(w http.ResponseWriter, r *http.Request){ var p *int //制造错误 *p = 100 io.WriteString(w,"<h1>hello,world</h1>") } func FormServer(w http.ResponseWriter, r *http.Request){ w.Header().Set("Content-Type","text/html") //设置响应头内容 w.Header().Set("wang","haijun") switch r.Method{ case "GET": io.WriteString(w,form) //如果是Get请求,则把form表单内容返回去 case "POST": r.ParseForm() //解析表单,获取表单内容 io.WriteString(w,r.Form["user"][0]) //获取表单内容,并返回给浏览器 io.WriteString(w,r.FormValue("user")) //获取表单内容,并返回给浏览器 io.WriteString(w," ") io.WriteString(w,r.Form["pwd"][0]) io.WriteString(w,r.FormValue("pwd")) } } func main(){ http.HandleFunc("/test1",logPanics(SimpleServer)) http.HandleFunc("/test2", FormServer) err :=http.ListenAndServe("0.0.0.0:80",nil) if err != nil { fmt.Println(err) } } func logPanics(handle http.HandlerFunc) http.HandlerFunc{ //接收一个http.HandlerFunc类型的参数,并返回一个http.HandlerFunc类型的函数 return func(writer http.ResponseWriter,r *http.Request){ defer func(){ if x:=recover(); x!= nil{ fmt.Printf("%v caught panic%v",r.RemoteAddr,x) } }() handle(writer,r) //相当于调用 SimpleServer函数,通过logPanics这个函数,即完成原来函数的功能,又增加了新的功能 } }
访问url:127.0.0.1/test1
页面没有报错,后台有错误,可以定向到日志中: