golang请求响应拦截与处理插件库mediary的使用

Golang请求响应拦截与处理插件库mediary的使用

概述

mediary是一个Golang库,允许您为http.Client添加拦截器,实现以下功能:

  • 将请求和/或响应转储到日志
  • 在发送请求前修改请求或在返回响应前修改响应
  • 使用Opentracing/Jaeger添加追踪信息
  • 向statsd发送指标
  • 其他功能,同时仍然使用"常规"的http.Client

基本用法

var client *http.Client
client = mediary.Init().AddInterceptors(your interceptor).Build()
client.Get("https://golang.org")

转储示例

client := mediary.Init().AddInterceptors(dumpInterceptor).Build()
client.Get("https://golang.org")

func dumpInterceptor(req *http.Request, handler mediary.Handler) (*http.Response, error) {
	if bytes, err := httputil.DumpRequestOut(req, true); err == nil {
		fmt.Printf("%s", bytes)

		//GET / HTTP/1.1
		//Host: golang.org
		//User-Agent: Go-http-client/1.1
		//Accept-Encoding: gzip
	}
	return handler(req)
}

拦截器

Interceptor是一个函数

type Interceptor func(*http.Request, Handler) (*http.Response, error)

Handler只是http.Roundtripper函数RoundTrip的别名

type Handler func(*http.Request) (*http.Response, error)

多个拦截器

可以链式添加多个拦截器

client := mediary.Init().
    AddInterceptors(First Interceptor, Second Interceptor).
    AddInterceptors(Third Interceptor).
    Build()

拦截器的工作流程如下:

  • 第一个拦截器:处理请求
    • 第二个拦截器:处理请求
      • 第三个拦截器:处理请求
        • Handler <-- 实际的HTTP调用
      • 第三个拦截器:处理响应
    • 第二个拦截器:处理响应
  • 第一个拦截器:处理响应

使用自定义客户端/传输

如果您已经有一个预配置的http.Client,也可以使用它

yourClient := &http.Client{}
yourClientWithInterceptor := mediary.Init().
    WithPreconfiguredClient(yourClient).
    AddInterceptors(your interceptor).
    Build()

完整示例

package main

import (
	"fmt"
	"net/http"
	"net/http/httputil"

	"github.com/HereMobilityDevelopers/mediary"
)

func main() {
	// 创建带拦截器的客户端
	client := mediary.Init().
		AddInterceptors(loggingInterceptor).
		AddInterceptors(addHeaderInterceptor).
		Build()

	// 发送请求
	resp, err := client.Get("https://golang.org")
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer resp.Body.Close()

	fmt.Printf("响应状态码: %d\n", resp.StatusCode)
}

// 日志拦截器
func loggingInterceptor(req *http.Request, handler mediary.Handler) (*http.Response, error) {
	// 打印请求信息
	if bytes, err := httputil.DumpRequestOut(req, true); err == nil {
		fmt.Printf("请求信息:\n%s\n", bytes)
	}

	// 继续处理请求
	resp, err := handler(req)

	// 打印响应信息
	if resp != nil && err == nil {
		fmt.Printf("响应状态码: %d\n", resp.StatusCode)
	}

	return resp, err
}

// 添加请求头拦截器
func addHeaderInterceptor(req *http.Request, handler mediary.Handler) (*http.Response, error) {
	// 添加自定义请求头
	req.Header.Add("X-Custom-Header", "mediary-example")
	
	// 继续处理请求
	return handler(req)
}

这个示例展示了如何使用mediary创建带有两个拦截器的HTTP客户端:

  1. loggingInterceptor - 记录请求和响应信息
  2. addHeaderInterceptor - 添加自定义请求头

通过mediary,您可以轻松地为HTTP客户端添加各种中间件功能,而不需要修改底层HTTP实现。


更多关于golang请求响应拦截与处理插件库mediary的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang请求响应拦截与处理插件库mediary的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang请求响应拦截与处理插件库mediary的使用

mediary是一个轻量级的Golang中间件库,专门用于HTTP请求和响应的拦截与处理。它提供了一种简单的方式来在HTTP客户端请求前后添加处理逻辑,类似于中间件模式。

基本概念

mediary的核心思想是允许你在HTTP请求发出前和收到响应后插入自定义处理逻辑,这些逻辑被称为"中间件"。每个中间件都可以修改请求或响应,或者执行其他操作如日志记录、认证等。

安装

go get github.com/HereMobilityDevelopers/mediary

基本用法

1. 创建带有中间件的HTTP客户端

package main

import (
	"fmt"
	"net/http"
	"log"

	"github.com/HereMobilityDevelopers/mediary"
)

func main() {
	// 创建带有中间件的客户端
	client := mediary.Init().WithDefaultClient()

	// 添加请求前中间件
	client.AddRequestInterceptors(func(req *http.Request) error {
		fmt.Println("请求URL:", req.URL)
		req.Header.Add("X-Custom-Header", "my-value")
		return nil
	})

	// 添加响应后中间件
	client.AddResponseInterceptors(func(resp *http.Response, err error) error {
		if err != nil {
			fmt.Println("请求出错:", err)
			return err
		}
		fmt.Println("响应状态码:", resp.StatusCode)
		return nil
	})

	// 使用客户端发送请求
	resp, err := client.Get("https://httpbin.org/get")
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	fmt.Println("最终响应状态:", resp.Status)
}

2. 链式调用

mediary支持链式调用,使代码更简洁:

client := mediary.Init().
	WithDefaultClient().
	AddRequestInterceptors(logRequest).
	AddResponseInterceptors(logResponse)

高级用法

1. 自定义HTTP客户端

client := mediary.Init().
	WithClient(&http.Client{
		Timeout: 30 * time.Second,
	}).
	AddRequestInterceptors(authMiddleware)

2. 多个中间件

可以添加多个中间件,它们会按照添加顺序执行:

client := mediary.Init().
	WithDefaultClient().
	AddRequestInterceptors(logRequest).
	AddRequestInterceptors(addAuthHeader).
	AddResponseInterceptors(logResponse).
	AddResponseInterceptors(checkStatusCode)

3. 错误处理

中间件可以返回错误,如果请求前中间件返回错误,请求将不会发送;如果响应后中间件返回错误,会传递给调用者:

client.AddRequestInterceptors(func(req *http.Request) error {
	if req.URL.Host == "blocked.com" {
		return fmt.Errorf("访问被阻止的域名")
	}
	return nil
})

实际应用示例

1. 认证中间件

func authMiddleware(req *http.Request) error {
	token := getAuthToken() // 实现获取token的逻辑
	req.Header.Set("Authorization", "Bearer "+token)
	return nil
}

client := mediary.Init().
	WithDefaultClient().
	AddRequestInterceptors(authMiddleware)

2. 日志中间件

func logRequest(req *http.Request) error {
	log.Printf("请求: %s %s", req.Method, req.URL)
	return nil
}

func logResponse(resp *http.Response, err error) error {
	if err != nil {
		log.Printf("请求错误: %v", err)
		return err
	}
	log.Printf("响应: %s %s - %d", resp.Request.Method, resp.Request.URL, resp.StatusCode)
	return nil
}

client := mediary.Init().
	WithDefaultClient().
	AddRequestInterceptors(logRequest).
	AddResponseInterceptors(logResponse)

3. 重试中间件

func retryMiddleware(resp *http.Response, err error) error {
	if err != nil || resp.StatusCode >= 500 {
		// 实现重试逻辑
		return fmt.Errorf("需要重试")
	}
	return nil
}

client := mediary.Init().
	WithDefaultClient().
	AddResponseInterceptors(retryMiddleware)

注意事项

  1. 中间件的执行顺序很重要,先添加的中间件会先执行
  2. 请求前中间件可以修改请求,响应后中间件可以修改响应
  3. 如果中间件返回错误,处理链会中断
  4. 对于复杂的中间件链,考虑将中间件拆分为单独的函数以提高可读性

mediary是一个轻量但功能强大的库,特别适合需要对HTTP请求和响应进行统一处理的场景,如API客户端库的开发。通过中间件模式,你可以将横切关注点(如认证、日志、错误处理等)与业务逻辑分离,使代码更加清晰和可维护。

回到顶部