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

Time:02-06

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)
}

CodePudding user response:

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)

CodePudding user response:

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

NewSingleHostReverseProxy returns a new ReverseProxy that routes URLs to the scheme, host, and base path provided in target. If the target's path is "/base" and the incoming request was for "/dir", the target request will be for /base/dir. NewSingleHostReverseProxy does not rewrite the Host header. To rewrite Host headers, use ReverseProxy directly with a custom Director policy.

func main() {
    http.HandleFunc("/", handleProxy(baseURL))
}

func handleProxy(target *url.URL) http.HandlerFunc {
    proxy := httputil.NewSingleHostReverseProxy(target)
    return func(w http.ResponseWriter, r *http.Request) {
        r.Header.Set("ectra-header", "foo")
        proxy.ServeHTTP(w, r)

    }
}

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

http.HandleFunc("/foo/", http.StripPrefix("/foo/",  handleProxy(baseURL)))
  •  Tags:  
  • Related