栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Go⽹络编程——http

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Go⽹络编程——http

Http概述 概念

Hypertext Transfer Protocol,超⽂本传输协议。是互联⽹应⽤最⼴泛的⽹络协议,定义了客户端和服务端之间请求与响应的传输标准。
HTTP是⼀个基于TCP/IP通信协议来传递数据,服务器传输超⽂本到本地浏览器的传送协议。HTTP协议⼯作于客户端-服务端架构上。浏览器可作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。它是⼀个⽆状态的请求/响应协议。
客户端请求消息和服务器响应消息都会包含请求头和请求体。HTTP请求头提供了关于请求或响应,发送实体的信息,如:Content-Type、ContentLength、Date等。当浏览器接收并显示⽹⻚前,此⽹⻚所在的服务器会返回⼀个包含HTTP状态码的信息头(server header)⽤以响应浏览器的请求。HTTP状态码的英⽂为HTTP Status Code。
下⾯是常⻅的HTTP状态码:

  • 200 - 请求成功
  • 301 - 资源(⽹⻚等)被永久转移到其它URL
  • 404 - 请求的资源(⽹⻚等)不存在
  • 413 - 由于请求的实体过⼤,服务器⽆法处理,因此拒绝请求。为防⽌客户端的连续请求,服务器可能会关闭连接。
  • 500 - 内部服务器错误
HTTP请求⽅法

常⽤⽅法: GetPostHead
Http定义了与服务器交互的不同⽅法,最基本的⽅法有4种,分别是**GET,POST,PUT,DELETE,**对应着对这个资源的查 ,改 ,增 ,删 4个操作。
另外还有个Head⽅法. 类似GET⽅法,只请求⻚⾯的⾸部,不响应⻚⾯Body部分,⽤于获取资源的基本信息,即检查链接的可访问性及资源是否修改。
GET和POST的区别

  • GET在浏览器回退时是⽆害的,⽽POST会再次提交请求。
  • GET产⽣的URL地址可以被Bookmark,⽽POST不可以。
  • GET请求会被浏览器主动cache,⽽POST不会,除⾮⼿动设置。
  • GET请求只能进⾏url编码,⽽POST⽀持多种编码⽅式。
  • GET请求参数会被完整保留在浏览器历史记录⾥,⽽POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有⻓度限制的,⽽POST没有。
  • 对参数的数据类型,GET只接受ASCII字符,⽽POST没有限制。
  • GET⽐POST更不安全,因为参数直接暴露在URL上,所以不能⽤来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。
    HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。
  • GET产⽣⼀个TCP数据包;POST产⽣两个TCP数据包。
    • 对于GET⽅式的请求,浏览器会把http header和data⼀并发送出去,服务器响应200(返回数据);
    • ⽽对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据))
HTTPS通信原理

HTTPS(Secure Hypertext Transfer Protocol)安全超⽂本传输协议 它是⼀个安全通信通道
HTTPS是HTTP over SSL/TLS,HTTP是应⽤层协议,TCP是传输层协议,在应⽤层和传输层之间,增加了⼀个安全套接层SSL。
服务器 ⽤RSA⽣成公钥和私钥把公钥放在证书⾥发送给客户端,私钥⾃⼰保存客户端⾸先向⼀个权威的服务器检查证书的合法性,如果证书合法,客户端产⽣⼀段随机数,这个随机数就作为通信的密钥,我们称之为对称密钥,⽤公钥加密这段随机数,然后发送到服务器服务器⽤密钥解密获取对称密钥,然后,双⽅就已对称密钥进⾏加密解密通信了。

Https的作⽤
  • 内容加密 建⽴⼀个信息安全通道,来保证数据传输的安全;
  • 身份认证 确认⽹站的真实性
  • 数据完整性 防⽌内容被第三⽅冒充或者篡改
    Https和Http的区别
  • https协议需要到CA申请证书。
  • http是超⽂本传输协议,信息是明⽂传输;https 则是具有安全性的ssl加密传输协议。
  • http和https使⽤的是完全不同的连接⽅式,⽤的端⼝也不⼀样,前者是80,后者是443。
  • http的连接很简单,是⽆状态的;HTTPS协议是由SSL+HTTP协议构建的可进⾏加密传输、身份认证的⽹络协议,⽐http协议安全。
http客户端实现

Go语⾔标准库内置了net/http包,涵盖了HTTP客户端和服务端的具体实现。
内置的net/http包,提供了最简洁的HTTP客户端实现,⽆需借助第三⽅⽹络通信库就可以直接使⽤HTTP中⽤的最多的GET和POST⽅式请求数据。

  • http.Get()
  • http.Post()
  • http.PostForm()
  • http.Head()
  • http.Do()
客户端基本⽅法
  1. ⼀个简单的get实现
    func main() {
    requestUrl := “http://www.baidu.com”
    response, err := http.Get(requestUrl)
    if err != nil {
    fmt.Println(“err:”,err);
    }
    defer response.Body.Close();
    fmt.Println(response.Body) }
    err: Get www.baidu.com: unsupported protocol scheme “”
    错误:不⽀持scheme为空的协议,这是什么情况呢,
    requestUrl改为requestUrl := “http://www.baidu.com”
    scheme反应出的就是协议名称
    ⼤家可以看到打印的是 &{0xc420124200 }
    Body是io.ReadCloser这个类型的对象
    response中的参数⼀般也⽐较多,我们需要的最多的通常是Body参数,⽤ioutil.ReadAll去转化io.ReadCloser类型,输出是byty[],再通过string()强制转换就能看到string了
    readBody, _ := ioutil.ReadAll(response.Body)
    fmt.Println(string(readBody))
    咱们这个是正确获取到了服务器响应的数据才能这么打印出来了,加⼊失败了呢,因此需要判断返回码,再去获取body的数据。
    if response.StatusCode == 200 {
    r, err := ioutil.ReadAll(response.Body)
    if err != nil {
    fmt.Println(err)
    }
    return string®
    }
  2. ⽅式⼀ 使⽤http.NewRequest
    先⽣成http.client -> 再⽣成 http.request -> 之后提交请求:client.Do(request)-> 处理返回结果,每⼀步的过程都可以设置⼀些具体的参数
  3. ⽅式⼆ 先⽣成client,之后⽤client.get/post…
    client结构⾃⼰也有⼀些发送api的⽅法,⽐如client.get,client.post,client.postform…等等。基本上涵盖了主要的http请求的类型,通常不进⾏什么特殊的配置的话,这样就可以了,其实client的get或者post⽅法,也是对http.Newerequest⽅法的封装,⾥⾯还额外添加了
    req.Header.Set(“Content-Type”, bodyType)⼀般⽤的话,也是ok的
  4. ⽅式三 http. Get/Post…
    具体实现的时候,还是采⽤的⽅式⼀模式,先⽣成⼀个默认的client,之后调⽤http.Newrequest⽅法。
    http.NewRequest
    client := &http.Client{}
    request, err := http.NewRequest(“GET”, requestUrl, nil)
    if err != nil {
    fmt.Println(err)
    }
    cookie := &http.Cookie{Name: “userId”, Value: strconv.Itoa(12345)}
    request.AddCookie(cookie) //request中添加cookie
    //设置request的header
    request.Header.Set(“Content-Type”, “text/html”)
    //Content-Length等
    response, err := client.Do(request)
  5. Post
    postvalue := url.Values{
    “theCityName”: {“天津”}, }
    body := bytes.NewBufferString(postvalue.Encode())
    response, err := http.Post(requestUrl, “application/x-www-form-urlencoded”,
    body) //Post⽅法
http服务端实现 服务端代码实现

func ServeHTTP(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
fmt.Println(“PATH: “, r.URL.Path)
fmt.Println(“HOST: “, r.URL.Host)
fmt.Println(“METHOD: “, r.Method)
fmt.Println()
//fmt.Fprintf(w, “

Index Page”)
io.WriteString(w, “ Index Page3”) }
func main() {
http.HandleFunc(”/”, ServeHTTP)
err := http.ListenAndServe(”:9000”, nil)
if err != nil {
log.Fatal(“ERROR: “, err)
}
}
函数func ListenAndServe(addr string, handler Handler) error内部进⾏封装更简洁地实现HTTP服务器。你可以看到它创建了Server类的⼀个对象,然后调⽤了刚才说的第⼀个函数。第2个参数是⼀个Hander,它是⼀个接⼝。这个接⼝很简单,只要某个struct有ServeHTTP(http.ResponseWriter, *http.Request)这个⽅法,那这个struct就⾃动实现了Hander接⼝。
ServeHTTP⽅法,他需要2个参数,⼀个是http.ResponseWriter,另⼀个是http.Request往http.ResponseWriter写⼊什么内容,浏览器的⽹⻚源码就是什么内容。http.Request⾥⾯是封装了,浏览器发过来的请求(包含路径、浏览器类型等等)。
OK,作为服务器我们会处理很多的请求,那下⼀步如何处理呢,难道switch r.URL.Path的值吗?那得多⾟苦。那有什么好的办法呢,这点go官⽅已经考虑到这点帮我们提供了⼀个⽅法叫做ServeMux,去分发任务。
下⾯介绍下ServeMux
ServeMux⼤致作⽤是,他有⼀张map表,map⾥的key记录的是r.URL.String(), ⽽value记录的是⼀个⽅法,这个⽅法和ServeHTTP是⼀样的,这样ServeMux是实现Handler接⼝的。这个⽅法有⼀个别名,叫HandlerFunc。
func main() {
mux := http.NewServeMux()
mux.HandleFunc(”/h”, func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, “hello”)
})
mux.HandleFunc(”/bye”, func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, “byebye”)
})
mux.HandleFunc(“/baidu”, func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, “http://www.baidu.com”,
http.StatusTemporaryRedirect)
})
mux.HandleFunc(“/hello”, sayhello)
http.ListenAndServe(“:9000”, mux) }
func sayhello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, “hello world”) }
回到开头,有让⼤家先忘掉http.HandleFunc(“/”, HandleIndex) 当http.ListenAndServe(“:9000”, nil)的第2个参数是nil时,http内部会⾃⼰建⽴⼀个叫DefaultServeMux的ServeMux,因为这个ServeMux是http⾃⼰维护的,如果要向这个ServeMux注册的话,就要⽤http.HandleFunc这个⽅法啦,现在看很简单吧。
func FileServer
func FileServer(root FileSystem) Handler
FileServer返回⼀个使⽤FileSystem接⼝root提供⽂件访问服务的HTTP处理器。
要使⽤操作系统的FileSystem接⼝实现,可使⽤http.Dir:
log.Fatal(http.ListenAndServe(“:8080”,
http.FileServer(http.Dir(“/usr/share/doc”))))

服务端获取客户端请求数据
  1. 获取GET参数
    ⽐较常⻅的是如下⽅式获取:
    r.ParseForm()
    if len(r.Form[“id”]) > 0 {
    fmt.Fprintln(w, r.Form[“id”][0])
    }
    其中r表示*http.Request类型,w表示http.ResponseWriter类型。
    r.Form是url.Values字典类型,r.Form[“id”]取到的是⼀个数组类型。因为http.request在解析参数的时候会将同名的参数都放进同⼀个数组⾥,所以这⾥要⽤[0]获取到第⼀个。
  2. 获取POST参数
    这⾥要分两种情况:
    普通的post表单请求,Content-Type=application/x-www-form-urlencoded 有⽂件上传的表单,Content-Type=multipart/form-data
    第⼀种情况⽐较简单,直接⽤PostFormValue就可以取到了。
    fmt.Fprintln(w, r.PostFormValue(“id”))
    第⼆种⽂件上传的表单这⾥不作讲解。
  3. 获取COOKIE参数
    cookie, err := r.Cookie(“id”)
    if err == nil {
    fmt.Fprintln(w, “Domain:”, cookie.Domain)
    fmt.Fprintln(w, “Expires:”, cookie.Expires)
    fmt.Fprintln(w, “Name:”, cookie.Name)
    fmt.Fprintln(w, “Value:”, cookie.Value) }
    r.Cookie返回*http.Cookie类型,可以获取到domain、过期时间、值等数据。
    注意
    application/x-www-form-urlencoded与 text/html 的区别
    若需使⽤r.PostForm、r.Form等⽅法,必须先调⽤r.ParseForm()
    客户端使⽤post提交数据到body时,若服务端需使⽤r.PostForm、r.Form等⽅法,客户端的请求体必须使⽤"Content-Type":“application/x-www-formurlencoded”) 类型,并且r.ParseForm()须放在ioutil.ReadAll(r.Body)解析body之前。否则数据将在body中。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/991215.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号