607283666
0618-12919046
导航

Go 语言 Web 框架—自界说 Server

发布日期:2023-02-16 01:14

本文摘要:这是定制篇的最后一节,解说 Server 的自界说。

yabo亚搏手机最新版app

这是定制篇的最后一节,解说 Server 的自界说。默认 Server通常情况下,Echo 通过如下方式启动一个 HTTP Server:e:=echo.New()e.GET("/",func(cecho.Context)error{returnc.String(http.StatusOK,"Hello,World!")})e.Logger.Fatal(e.Start(":2020"))我们打开源码一探究竟://StartstartsanHTTPserver.func(e*Echo)Start(addressstring)error{e.Server.Addr=addressreturne.StartServer(e.Server)}原来挪用的是 StartServer,参数是默认的 Server 实例,它是一个 http.Server 的指针类型。自界说 Server知道了 Echo#Start 最终挪用的是 Echo#StartServer,而且它的参数是一个*http.Server 类型,所以自界说一个 Server 很容易。我们先看看 http.Server 这个结构。

typeServerstruct{//指定 TCP 的监听地址,形式:"host:port"。如果空,则使用":http",即 80端口Addrstring//当前服务器的Handler,如果未设置,使用http.DefaultServeMuxHandlerHandler//TLS设置TLSConfig*tls.Config//读取整个request(包罗body)的最大允许时间(超时时间)ReadTimeouttime.Duration//从 Go1.8 开始增加。

只是读取请求头的最大允许时间(超时时间)ReadHeaderTimeouttime.Duration//Go1.8//和ReadTimeout对应,这是写response的最大允许时间(超时时间)WriteTimeouttime.Duration//从 Go1.8 开始增加。下个请求到来前允许的最大空闲时间(keep-alive 启用时)。

//如果是0,使用 ReadTimeout,都为0,不会超时。IdleTimeouttime.Duration//Go1.8//允许的最大请求头(单元字节),默认值DefaultMaxHeaderBytesMaxHeaderBytesint//其他字段忽略。}默认情况下启动的 Server,超时时间是 0,也就是不会超时。

我们自界说一个 Server,设置超时时间:s:=&http.Server{Addr:":2020",ReadTimeout:10*time.Second,WriteTimeout:10*time.Second,}e.Logger.Fatal(e.StartServer(s))为了利便验证,我们将超时时间设置的较短:10s,实际项目这个肯定太短了。验证读超时是否生效往下看之前,你想想用什么措施可以验证?因为 HTTP 是基于 TCP 的,我们可以简朴的通过建设 TCP 毗连,然后等候一段时间后,再发送 HTTP 报文,详细代码如下:funcmain(){conn,err:=net.Dial("tcp","127.0.0.1:2020")iferr!=nil{panic(err)}time.Sleep(11*time.Second)fmt.Fprintf(conn,"GET/HTTP/1.0rnrn")status,err:=bufio.NewReader(conn).ReadString('n')fmt.Println(status,err)}通过修改 Sleep 的时间来控制等候时间,可以看看 10s 以内是否乐成(恰好 10s 可能也会失败),10s 以上又是什么情况。

注意,这里的 HTTP/1.0 不能改为 1.1 等,否则得提供 Host 头部Sleep 设置为 11s ,运行客户端后,如果返回 EOF,则讲明超时设置生效了。自界说 ListenerEcho 框架支持自界说 Listener,即通过 Echo#Listener 举行设置。例如:l,err:=net.Listen("tcp",":1323")iferr!=nil{e.Logger.Fatal(l)}e.Listener=le.Logger.Fatal(e.Start(""))什么场景下会需要自界说?或者说为什么 Echo 要让用户可以自界说 Listener?我认为有两种思量:Listener 支持设置,详细就是 net.ListenConfig 类型。

实际上,net 包中,net.Listen() 函数就是用了这个类型获取 Listener 实例;除了使用 net.Listen 获取一个 Listener 接口的实破例,另有其他的方式可以获取 Listener 接口的实例;UnixListener我们着重看看第 2 种情况。net.Listener 是一个接口。在 net 库中,有 TCPListener 和 UnixListener,除此之外,其他的 Listener 都是基于这两种。好比 net.FileListener() 函数,最终是 TCPListener。

一般我们使用的就是 TCPListener,如果想在 echo 中使用 UnixListener,如何实现?(这个例子没有太多现实意义)funcmain(){unixAddr,err:=net.ResolveUnixAddr("unix","/tmp/echo.sock")iferr!=nil{panic(err)}unixListener,err:=net.ListenUnix("unix",unixAddr)iferr!=nil{panic(err)}e:=echo.New()e.GET("/",func(ctxecho.Context)error{returnctx.String(http.StatusOK,"Hello Unix!")})e.Listener=unixListenere.Logger.Fatal(e.Start(""))}因为基于 Unix Domain Socket,所以,没法直接浏览器会见。写一个测试法式:funcmain(){unixAddr,err:=net.ResolveUnixAddr("unix","/tmp/echo.sock")iferr!=nil{panic(err)}conn,err:=net.DialUnix("unix",nil,unixAddr)iferr!=nil{panic(err)}fmt.Fprintf(conn,"GET/HTTP/1.0rnrn")body,err:=ioutil.ReadAll(conn)iferr!=nil{panic(err)}deferconn.Close()fmt.Println(string(body))}客户端能够输出:HTTP/1.0200OKContent-Type:text/plain;charset=UTF-8Date:Wed,25Mar202006:35:12GMTContent-Length:13Hello Unix!表现乐成!再提醒下,一般不会界说 Listener,你知晓能界说即可。TLS 相关这里顺便先容下 Echo 对 TLS 的支持。

一般来说是用不到的,因为实际中,我们会使用 Web Server 举行反向署理,由 Web Server 来处置惩罚 TLS。但相识相关内容还是有利的。HTTPS Server看下相应的方法签名:func(e*Echo)StartTLS(addressstring,certFile,keyFileinterface{})(errerror)相比 Echo#Start 方法,StartTLS 多了两个参数:certFile 和 keyFile。

yabo亚搏手机最新版app

这两个参数是什么意思?这里简朴先容下,知晓什么意思即可。certFile:证书keyFile:私钥net/http 包,这两个参数是字符串,代表两个文件的路径。Echo 对此举行了扩展,除了可以代表文件的路径,还可以是字节数组,表现证书和私钥的详细内容。

CA 证书可以购置,也可以申请免费的(阿里云、七牛云都有),也可以使用 let’s encrypt 免费证书。这里我们先自己生成证书,当地验证。(注意,自己生成的证书,浏览器是不认的)证书生成证书的生成可以用 Linux/Mac 的 OpenSSL 工具链。

对于一个网站,首先必须有自己的私钥,私钥的生成方式为:$cdgo-cache-example#切换到我们的项目根目录$opensslgenrsa-outserver.key2048会在当前目录下生成一个 server.key 文件,这就是私钥。使用私钥就可以生成证书了。OpenSSL 使用 x509 下令生成证书。

这里需要区分两个观点:证书(certificate)和证书请求(certificate sign request)证书是自签名或 CA 签名过的凭据,用来举行身份认证证书请求是对签名的请求,需要使用私钥举行签名x509 下令可以将证书和证书请求相互转换。从私钥可以生成自签名证书:(跳过了证书请求,一步到位)opensslreq-new-x509-keyserver.key-outserver.crt-days365req 下令会通过下令行要求用户输入国家、地域、组织等信息,这些信息会附加在证书中展示给毗连方。

Youareabouttobeaskedtoenterinformationthatwillbeincorporatedintoyourcertificaterequest.WhatyouareabouttoenteriswhatiscalledaDistinguishedNameoraDN.TherearequiteafewfieldsbutyoucanleavesomeblankForsomefieldstherewillbeadefaultvalue,Ifyouenter'.',thefieldwillbeleftblank.-----CountryName(2lettercode)[]:CNStateorProvinceName(fullname)[]:BeijingLocalityName(eg,city)[]:BeijingOrganizationName(eg,company)[]:studygolangOrganizationalUnitName(eg,section)[]:CommonName(eg,fullyqualifiedhostname)[]:localhostEmailAddress[]:polaris@studygolang.com以上下令会在当前目录生成 server.crt 文件。这样我们有了上面需要的 cert 和 key。验证当地的 HTTPS Server在 go-cache-example 项目中的 cmd/custom/main.go 包罗如下代码:funcmain(){e:=echo.New()e.GET("/",func(ctxecho.Context)error{returnctx.String(http.StatusOK,"Hello TLS!")})e.Logger.Fatal(e.StartTLS(":2020","server.crt","server.key"))}启动服务:go run cmd/custom/main.go______/__/___//___/_//__/_/_/___/__/_//_/___/v4.1.15Highperformance,minimalistGowebframeworkhttps://echo.labstack.com____________________________________O/_______O⇨httpsserverstartedon[::]:2020打开 Chrome 浏览器,请求:https://localhost:2020 (注意是 HTTPS),泛起如下错误:在浏览器输出:chrome://flags/#allow-insecure-localhost ,高亮的置为 Enabled,Reload Chrome。

再次请求 https://localhost:2020 ,能正常输出:Hello TLS!讲明乐成了。通过 FireFox 浏览器,可以利便看到,我们这个服务支持 HTTP/2:Echo 还支持自动 TLS,即:Echo#StartAutoTLS 方法,它从 https://letsencrypt.org 获取证书。这涉及到正式域名等,在此不演示!自界说 HTTP/2 Cleartext Server默认情况下,HTTP/2 是基于 TLS 的。

上面也看到,当是 HTTPS Server 时,浏览器支持 HTTP/2,默认使用了它。如果我们想使用 HTTP/2,可是又不想使用 TLS,可以吗?这就是 H2C,即:HTTP/2 Cleartext Server。从 Echo4.1.15 开始支持启动 H2C 服务器:func(e*Echo)StartH2CServer(addressstring,h2s*http2.Server)(errerror)Go 从 1.6 开始,尺度库 net/http 支持 HTTP/2,Go1.8 支持 HTTP/2 的 Push。

Go 对 HTTP/2 的支持,最初通过 golang.org/x/net/http2 包实现。Echo 中,上面方法的参数 http2.Server 就是 golang.org/x/net/http2 包中的。实现一个支持 H2C 的 HTTP Server:funcmain(){e:=echo.New()e.GET("/",func(ctxecho.Context)error{fmt.Println(ctx.Request().Proto)returnctx.String(http.StatusOK,"Hello HTTP/2!")})server:=&http2.Server{MaxConcurrentStreams:250,MaxReadFrameSize:1048576,IdleTimeout:10*time.Second,}e.Logger.Fatal(e.StartH2CServer(":2020",server))}然而,因为现代的浏览器都不支持 H2C,所以测试我们通过 curl 来举行。$curl-v--http2-khttp://localhost:2020*Trying::1...*TCP_NODELAYset*Connectedtolocalhost(::1)port2020(#0)>GET/HTTP/1.1>Host:localhost:2020>User-Agent:curl/7.64.1>Accept:*/*>Connection:Upgrade,HTTP2-Settings>Upgrade:h2c>HTTP2-Settings:AAMAAABkAARAAAAAAAIAAAAA><HTTP/1.1101SwitchingProtocols<Connection:Upgrade<Upgrade:h2c*Received101*UsingHTTP2,serversupportsmulti-use*Connectionstatechanged(HTTP/2confirmed)*CopyingHTTP/2datainstreambuffertoconnectionbufferafterupgrade:len=0*Connectionstatechanged(MAX_CONCURRENT_STREAMS==250)!<HTTP/2200<content-type:text/plain;charset=UTF-8<content-length:15<date:Thu,26Mar202008:20:58GMT<*Connection#0tohostlocalhostleftintactHello HTTP/2!* Closing connection 0而且服务端的输出也确实证明是 HTTP/2。

另外可以通过 Echo#DisableHTTP2 禁用 HTTP/2。至此,关于 Server 的定制就先容完了。Echo 的定制也全部解说完。


本文关键词:语言,Web,框架,—,自,界说,Server,这是,定制,篇,yabo亚搏手机最新版app

本文来源:yabo亚搏手机最新版app-www.yunzhoupx.com