原来你也玩Hertz

282 阅读10分钟

前置知识

GET请求适用于以下情况:

  1. 获取数据:当需要从服务器获取数据,而不对服务器进行修改或提交数据时,可以使用GET请求。比如浏览网页、查看博客文章等。
  2. 幂等性操作:幂等性操作指的是多次执行相同的操作,对服务器产生的影响是一样的,不会对服务器产生副作用。GET请求是幂等的,因此在执行幂等性操作时,可以使用GET请求。
  3. 缓存数据:由于GET请求的幂等性特性,响应结果可以被缓存起来,以供后续重复请求时使用。这样可以节省网络资源,提高响应速度。
  4. 不涉及敏感信息:GET请求将请求参数包含在URL中,因此不适合传输敏感信息。一般来说,GET请求适合传输非敏感、公开的数据。
  5. 简单快速:相对于POST请求,GET请求的参数较为简洁,直接附加在URL中,发送请求的过程相对简单和迅速。

POST请求适用于以下情况:

  1. 提交数据:当需要向服务器提交数据,以便在服务器端进行处理、存储或修改时,可以使用POST请求。比如用户注册、表单提交等。
  2. 非幂等操作:非幂等操作指的是多次执行相同操作,对服务器产生的影响可能不一样,可能会对服务器状态产生副作用。POST请求是非幂等的,因此在执行非幂等操作时,应该使用POST请求。
  3. 传输敏感信息:相对于GET请求,POST请求将数据放在请求体中,而不是URL中,因此更适合用于传输敏感信息,如用户密码、信用卡号等。
  4. 大量数据传输:由于POST请求将数据放在请求体中,并没有长度限制(HTTP协议本身没有限制),因而适合用于传输较大量的数据。
  5. 安全性要求高:相对于GET请求,POST请求的数据不暴露在URL中,更为安全,适用于需要保护数据安全的场景。

PUT请求适用于以下情况:

  1. 更新资源:当需要对服务器上的资源进行更新或替换时,可以使用PUT请求。PUT请求会将请求的内容完全替换原始资源,即将整个资源替换为请求中的新内容。
  2. 幂等操作:PUT请求是幂等的,即多次执行相同的PUT请求结果是一样的,对服务器产生的影响也是一样的。
  3. 没有副作用:PUT请求不应该对服务器产生除了更新资源之外的其他副作用,不应该引起服务器状态的变化。
  4. 完整更新:PUT请求要求发送整个资源的内容,而不仅仅是部分修改。因此,适合用于对整个资源进行完整更新的场景。

PATCH请求适用于以下情况:

  1. 部分更新资源:当需要对服务器上的资源进行部分更新或修改时,可以使用PATCH请求。PATCH请求不同于PUT请求,它只会将请求中给出的部分资源应用到目标资源上,而不是替换整个资源。
  2. 幂等操作:PATCH请求也是幂等的,即多次执行相同的PATCH请求结果是一样的,对服务器产生的影响也是一样的。
  3. 没有副作用:PATCH请求不应该对服务器产生除了更新资源之外的其他副作用,不应该引起服务器状态的变化。
  4. 部分更新:PATCH请求要求请求体中只包含需要更新的部分内容,而不是整个资源的内容。因此,适合用于对资源进行局部更新的场景。

HEAD请求适用于以下情况:

  1. 获取资源的元数据:当需要获取服务器上的资源的元数据,而不需要获取实际内容时,可以使用HEAD请求。HEAD请求与GET请求类似,但是不会返回实际的响应体,只返回对应的响应头部信息。
  2. 检查资源是否存在或可用:通过发送HEAD请求,客户端可以检查某个资源是否存在或是否可用。服务器会返回相应的响应状态码(如200 OK表示资源存在,404 Not Found表示资源不存在)以及响应头部信息,但不返回具体的响应内容。
  3. 减少网络传输:由于HEAD请求只返回响应头部信息,而不返回响应体内容,因此可以减少网络传输的数据量和响应时间。

OPTIONS请求适用于以下情况:

  1. 获取服务器端支持的HTTP方法:通过发送OPTIONS请求,客户端可以获取服务器支持的HTTP方法列表,以确定可以对目标资源执行哪些操作。服务器会在响应头部的Allow字段中返回支持的HTTP方法。
  2. 获取资源的通信选项:OPTIONS请求也可以用于获取关于目标资源的通信选项信息。服务器可以在响应头部的其他自定义字段中返回有关目标资源的特定选项信息。
  3. CORS(跨域资源共享)预检测:在进行跨域请求时,浏览器会发送OPTIONS请求进行预检测,以确认实际请求是否安全可接受。服务器需要响应OPTIONS请求,并在响应头部中提供相应的CORS信息,以允许或拒绝实际请求的发送。

DELETE请求适用于以下情况:

  1. 删除资源:当需要从服务器上删除资源时,可以使用DELETE请求。DELETE请求会将目标资源完全删除。
  2. 幂等操作:DELETE请求也是幂等的,即多次执行相同的DELETE请求结果是一样的,对服务器产生的影响也是一样的。
  3. 没有副作用:DELETE请求不应该对服务器产生除了删除资源之外的其他副作用,不应该引起服务器状态的变化。

any

Any方法是用于注册处理HTTP请求的方法,它可以匹配所有的HTTP方法(GET、POST、PUT、DELETE等)。

使用"ANY"方法可以方便地处理多种HTTP方法的请求,而不需要显式地指定每一种具体的方法。然而,需要注意的是,这种处理方式可能引起潜在的安全风险和接口设计混乱,因为不同的HTTP方法具有不同的语义和用途。

handle

 h.Handle("LOAD", "/load", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "load")
     })

这个方法支持用户手动传入 HTTP Method 用来注册方法,当用于注册普通的 HTTP Method 方法时和上述的方法作用是一致的,并且这个方法同时也支持用于注册自定义 HTTP Method 方法

RegisterRoute

 // RegisterRoute static route
 func RegisterRoute(h *server.Hertz) {
 ​
     h.StaticFS("/", &app.FS{Root: "./", GenerateIndexPages: true})
     //StaticFS 方法是 Hertz 框架提供的一个函数,它用于将静态文件服务与指定的路径进行映射。在这里,我们将根目录 ./ (即当前项目所在的目录)映射到了根路径 /。
 ​
     h.GET("/get", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "get")
     })
     //普通的get方法
 ​
     h.POST("/post", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "post")
     })
     //普通的post方法
 ​
     h.PUT("/put", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "put")
     })
     //普通的put方法
 ​
     h.DELETE("/delete", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "delete")
     }) //普通的delete方法
 ​
     h.PATCH("/patch", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "patch")
     }) //普通的patch方法
 ​
     h.HEAD("/head", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "head")
     }) //普通的head方法
 ​
     h.OPTIONS("/options", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "options")
     }) //普通的options方法
 ​
     h.Any("/ping_any", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "any")
     }) //普通的any方法,可以匹配任何的http请求
 ​
     h.Handle("LOAD", "/load", func(ctx context.Context, c *app.RequestContext) {
         c.String(consts.StatusOK, "load")
     })
     //不普通的handle方法
 ​
 }

展示了全部的http请求的获取方法,但是用的string响应

分组

 func RegisterGroupRoute(h *server.Hertz) {
     // Simple group: v1
     v1 := h.Group("/v1")
     {
         // loginEndpoint is a handler func
         v1.GET("/get", func(ctx context.Context, c *app.RequestContext) {
             c.String(consts.StatusOK, "get")
         })
         v1.POST("/post", func(ctx context.Context, c *app.RequestContext) {
             c.String(consts.StatusOK, "post")
         })
     }
 ​
     // Simple group: v2
     v2 := h.Group("/v2")
     {
         v2.PUT("/put", func(ctx context.Context, c *app.RequestContext) {
             c.String(consts.StatusOK, "put")
         })
         v2.DELETE("/delete", func(ctx context.Context, c *app.RequestContext) {
             c.String(consts.StatusOK, "delete")
         })
     }
 }

非常容易理解的分组捏

分组但是中间件

 // RegisterGroupRouteWithMiddleware route groups that incorporate middleware
 func RegisterGroupRouteWithMiddleware(h *server.Hertz) {
     // The following example uses the BasicAuth middleware in a route group.
 ​
     // Sample Code 1:
     //
     // Bind the middleware directly to the routing group
     example1 := h.Group("/example1", basic_auth.BasicAuth(map[string]string{"test": "test"}))
     example1.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
         ctx.String(consts.StatusOK, "ping")
     })
     
   /*
   
   使用了 BasicAuth 中间件。这意味着访问该路由组上的任何路由都需要进行基本身份验证。例如,使用用户名为 "test" 和密码为 "test" 的凭证,可以访问所有路由。
 ​
 这里我们使用 basic_auth.BasicAuth(map[string]string{"test": "test"}) 函数创建了中间件实例,该函数接受一个 map 类型的参数,用于存储允许访问的用户名和密码的键值对。
   
   */
 ​
     // Sample Code 2:
     //
     // use `Use` method
     example2 := h.Group("/example2")
     example2.Use(basic_auth.BasicAuth(map[string]string{"test": "test"}))
     example2.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
         ctx.String(consts.StatusOK, "ping")
     }
 ​
  /*
 example2 是另一个路由组,它也使用了 BasicAuth 中间件。但是,在这个例子中,我们使用了 Use 方法来将中间件绑定到路由组上,而不是在路由组定义上直接指定中间件。
 ​
 Use 方法可以接受一个或多个中间件作为参数。在这个例子中,我们只使用了 BasicAuth 中间件。
 */                
               
                 )
     
     
     
 }

在 Postman 中,可以通过设置请求头部来添加基本身份验证凭证。具体的步骤如下:

  1. 打开 Postman 并创建一个新请求。
  2. 在请求编辑器中,进入 "Headers" 选项卡。
  3. 点击 "Add header" 按钮,添加一个名为 "Authorization" 的请求头部。
  4. 在 "Authorization" 请求头部的值中,输入 "Basic" 后面跟一个空格和 Base64 编码后的用户名和密码串。

例如,如果要使用用户名为 "test" 和密码为 "test" 的凭证进行身份验证,在 "Authorization" 请求头部的值中应该输入 "Basic dGVzdDp0ZXN0"。其中,用户名和密码的字符串 "test:test" 经过 Base64 编码后得到 "dGVzdDp0ZXN0"。请注意,这里需要在用户名和密码之间添加一个冒号 ":" 来拼接成一个字符串,同时也需要在 "Basic" 和 Base64 编码后的字符串之间添加一个空格。

完成以上步骤后,就可以发送带有基本身份验证凭证的请求了。Postman 会自动将 "Authorization" 请求头部添加到请求中,并将凭证传递给服务器。

获得数据

 // RegisterParaRoute parameter route
 func RegisterParaRoute(h *server.Hertz) {
     // This handler will match: "/hertz/version", but will not match : "/hertz/" or "/hertz"
     h.GET("/hertz/:version", func(ctx context.Context, c *app.RequestContext) {
         version := c.Param("version")
         c.String(consts.StatusOK, "Hello %s", version)
     })
 ​
     // However, this one will match "/hertz/v1/" and "/hertz/v2/send"
     h.GET("/hertz/:version/*action", func(ctx context.Context, c *app.RequestContext) {
         version := c.Param("version")
         action := c.Param("action")
         message := version + " is " + action
         c.String(consts.StatusOK, message)
     })
 ​
     // For each matched request Context will hold the route definition
     h.POST("/hertz/:version/*action", func(ctx context.Context, c *app.RequestContext) {
         // c.FullPath() == "/hertz/:version/*action" // true
         c.String(consts.StatusOK, c.FullPath())
     })
 }

非常的通俗易懂

其他

 func RegisterAnonFunOrDecRoute(h *server.Hertz) {
     h.AnyEX("/ping", func(c context.Context, ctx *app.RequestContext) {
         ctx.String(consts.StatusOK, app.GetHandlerName(ctx.Handler()))
     }, "ping_handler")
 }
  • h:是一个 server.Hertz 实例,表示 Hertz 服务器的引用。

  • h.AnyEX:是 Hertz 服务器提供的方法,用于注册任意类型的请求(GET、POST、PUT、DELETE 等)。

  • "/ping":是注册路径为 /ping

  •  func(c context.Context, ctx *app.RequestContext)
    

    :是匿名函数,作为请求处理程序被注册。

    • c:是请求的上下文对象,提供了与请求相关的信息和功能。
    • ctx:是一个自定义的 app.RequestContext 对象,表示应用程序特有的上下文信息。
  • ctx.String(consts.StatusOK, app.GetHandlerName(ctx.Handler())):是对请求的处理逻辑。它通过 ctx.String 方法向客户端返回一个字符串,状态码为 consts.StatusOK(可能是一个常量,表示请求成功)。

  • "ping_handler":是一个可选参数,用于标识该处理程序的名称。

整个函数的作用是将一个处理 /ping 路径的请求的处理程序注册到 Hertz 服务器中。当有请求访问 /ping 时,匿名函数会被调用,并返回一个字符串作为响应。

日志处理

 // RegisterGetRoutesInfo Get route info
 func RegisterGetRoutesInfo(h *server.Hertz) {
     // 注册 "getRoutesInfo"(GET /getRoutesInfo)的处理程序
     h.GET("/getRoutesInfo", func(c context.Context, ctx *app.RequestContext) {
         ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
     })
 ​
     // 获取所有路由信息
     routeInfo := h.Routes()
 ​
     // 将所有路由信息输出到日志中
     hlog.Info(routeInfo)
 }