添加头部的最佳请求转发方式是什么?

huangapple go评论78阅读模式
英文:

What whould be the best way to forward a request by adding headers?

问题

我刚开始使用Golang,并且想用Go重新制作我已经工作的NodeJS/TypeScript应用程序。

我的API的一个端点简单地添加了服务器生成的授权头,并向远程API发送请求。基本上,通过调用我的API来为我填充这些头部,而不是调用远程API。

这是我目前正在编写的代码:

func Endpoint(ctx *fiber.Ctx) error {
    url := "https://api.twitch.tv" + ctx.OriginalURL()

    req, _ := http.NewRequest(http.MethodGet, url, nil)

    req.Header.Set("Authorization", "Bearer ---------")
    req.Header.Set("Client-Id", "---------")

    client := &http.Client{}
    res, err := client.Do(req)

    // 临时错误处理
    if err != nil {
        log.Fatalln(err)
    }

    body, err := ioutil.ReadAll(res.Body)

    // 临时错误处理
    if err != nil {
        log.Fatalln(err)
    }

    var forwardedBody interface{}

    json.Unmarshal(body, &forwardedBody)

    return ctx.Status(fiber.StatusOK).JSON(forwardedBody)
}

我想知道我是否在正确的步骤上,因为发出请求,使用ioutil解析JSON响应,然后将其反序列化并发送回去,似乎对于我想要实现的简单性来说有点过于复杂了?

编辑:感谢您的帮助,这是我将要采用的代码:

func Endpoint(ctx *fiber.Ctx) error {
    url := "https://api.twitch.tv" + ctx.OriginalURL()

    req, _ := http.NewRequest(http.MethodGet, url, nil)

    req.Header.Set("Authorization", "Bearer ---------")
    req.Header.Set("Client-ID", "---------")

    client := &http.Client{}
    res, err := client.Do(req)

    if err != nil {
        return ctx.SendStatus(fiber.StatusBadRequest)
    }

    ctx.Set("Content-Type", "application/json; charset=utf-8")

    return ctx.Status(res.StatusCode).SendStream(res.Body)
}
英文:

I just started to use Golang and I want to remake my already working NodeJS/TypeScript app in Go.

One endpoint of my API simply adds server-side generated authorization headers and sends a request to a remote API. Basically filling those headers for me by calling my API instead of the remote API.

This is what I am currently writing

func Endpoint(ctx *fiber.Ctx) error {
	url := "https://api.twitch.tv" + ctx.OriginalURL()

	req, _ := http.NewRequest(http.MethodGet, url, nil)

	req.Header.Set("Authorization", "Bearer ---------")
	req.Header.Set("Client-Id", "---------")

	client := &http.Client{}
	res, err := client.Do(req)

	// temporary error handling
	if err != nil {
		log.Fatalln(err)
	}

	body, err := ioutil.ReadAll(res.Body)

	// temporary error handling
	if err != nil {
		log.Fatalln(err)
	}

	var forwardedBody interface{}

	json.Unmarshal(body, &forwardedBody)

	return ctx.Status(fiber.StatusOK).JSON(forwardedBody)
}

I'd like to know if I am on the right steps, because making a request, parsing the JSON response with ioutil then unmarshall it to send it back seems kind of overboard for the simplicity of what I am trying to achieve ?

Edit: Thank you for the help, this is what I will be going for

func Endpoint(ctx *fiber.Ctx) error {
	url := "https://api.twitch.tv" + ctx.OriginalURL()

	req, _ := http.NewRequest(http.MethodGet, url, nil)

	req.Header.Set("Authorization", "Bearer ---------")
	req.Header.Set("Client-ID", "---------")

	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		return ctx.SendStatus(fiber.StatusBadRequest)
	}

	ctx.Set("Content-Type", "application/json; charset=utf-8")

	return ctx.Status(res.StatusCode).SendStream(res.Body)
}

答案1

得分: 2

你可以使用httputil.ReverseProxy。它接受一个基本URL并将请求转发到该URL,同时连接路径。

ReverseProxy是一个HTTP处理程序,它接收传入的请求并将其发送到另一个服务器,然后将响应代理回客户端。

http.Handle("/", &httputil.ReverseProxy{
	Director: func(r *http.Request) {
		r.URL.Scheme = "https"
		r.URL.Host = "go.dev"
		r.Host = r.URL.Host
		r.Header.Set("X-Foo", "Bar")
	},
})

如果你不是从根路径/提供服务,你可以使用StripPrefix

http.HandleFunc("/foo/", http.StripPrefix("/foo/", proxy))

还有一个辅助函数NewSingleHostReverseProxy,它可能会省去你自己配置代理结构的步骤。但我认为最好还是将Host头与你的自定义头一起设置。

英文:

You can use httputil.ReverseProxy. Which takes a base URL and forwards requests to the base URL, concatenating the path.

> ReverseProxy is an HTTP Handler that takes an incoming request and sends it to another server, proxying the response back to the client.

http.Handle("/", &httputil.ReverseProxy{
	Director: func(r *http.Request) {
		r.URL.Scheme = "https"
		r.URL.Host = "go.dev"
		r.Host = r.URL.Host
		r.Header.Set("X-Foo", "Bar")
	},
})

If you are not serving this from the root path / you can use StripPrefix.

http.HandleFunc("/foo/", http.StripPrefix("/foo/", proxy)

There is also a helper function NewSingleHostReverseProxy, which possibly removes the need to configure the proxy struct yourself. But I think it will be better to set the Host header along with your custom header.

答案2

得分: 1

你不需要尝试将数据解析为JSON。如果你的任何一个端点不返回JSON,这样做会有问题,所以直接将body注入到响应中即可:

body, err := ioutil.ReadAll(res.Body)

// 临时错误处理
if err != nil {
    log.Fatalln(err)
}

// 将内部响应的body注入到实际响应中,以便返回
ctx.Response().SetBody(body)

return cx.Status(fiber.StatusOK)
英文:

You don't need to attempt to parse the data as JSON. This will be problematic if any of your endpoints don't return JSON, anyway, so just inject the body directly into the response:

body, err := ioutil.ReadAll(res.Body)

// temporary error handling
if err != nil {
    log.Fatalln(err)
}

// Inject the body from the inner response into the actual response so it can be returned
ctx.Response().SetBody(body)

return cx.Status(fiber.StatusOK)

huangapple
  • 本文由 发表于 2022年2月5日 09:51:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/70994704.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定