http web 开发

1.http请求包

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8      告诉服务器客户端能接收的数据,例如:html,xhtml,xml等等

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 URL:http://127.0.0.1:8080/      请求url

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

HTTP请求的方法:
HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式
 
1、OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
2、HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
3、GET
向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_url
4、POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
5、PUT
向指定资源位置上传其最新内容
6、DELETE
请求服务器删除Request-URL所标识的资源
7、TRACE
回显服务器收到的请求,主要用于测试或诊断
8、CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
注意:
1)方法名称是区分大小写的,当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Mothod Not Allowed);当服务器不认识或者不支持对应的请求方法时,应返回状态码501(Not Implemented)。
2)HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的,此外除上述方法,特定的HTTP服务器支持扩展自定义的方法。
 

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

页面没有报错,后台有错误,可以定向到日志中:

原文地址:https://www.cnblogs.com/wanghaijun999/p/8479846.html