Marius
Marius

Reputation: 597

Go http request redirect

I am writing an API whichs has to redirect incoming requests to another service, the response must be forwarded to the original requester.

I figured a simple function like below should do the trick, but I was wrong.

I receive the data from my redirected response, however when I send it back to the initial request I receive this response without any data Could not get response. Error: socket hang up

If I try to execute the very same request using postman straight to the redirect URL it works perfectly fine.

func initialAssetsHandler(w http.ResponseWriter, r *http.Request) {
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    resp, err := http.Post(conf.redirectURL, "application/json", bytes.NewReader(body))
    if err != nil {
        log.Error(err)
    }
    defer resp.Body.Close()
    buf := new(bytes.Buffer)
    buf.ReadFrom(resp.Body)
    log.Info(string(buf.Bytes()))

    var data json.RawMessage
    if err = json.NewDecoder(resp.Body).Decode(&data); err != nil {
        fmt.Println(err)
        return
    }
    helper.SendJsonRaw(w, 200, data)
}

Here is the SendJsonRaw function:

func SendJsonRaw(w http.ResponseWriter, status int, r json.RawMessage) error {
    w.Header().Set(HeaderContentType, MimeApplicationJSON)
    w.WriteHeader(status)
    _, err := w.Write(r)
    return err
}

Upvotes: 0

Views: 846

Answers (1)

mkopriva
mkopriva

Reputation: 38313

The r.Body is read by the json decoder up to EOF, then when you pass it to the redirect request it looks empty to the http.Client and therefore it sends no body. You need to retain the content of the body.

For example you can do the following:

func initialAssetsHandler(w http.ResponseWriter, r *http.Request) {
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        fmt.Println(err)
        return
    }

    var initialAssets TagAssets
    if err := json.Unmarshal(&initialAssets, body); err != nil {
        if !strings.Contains(err.Error(), "json: invalid use of ,string struct tag, trying to unmarshal") {
            helper.SendJsonError(w, http.StatusBadRequest, err)
            return
        }
    }

    resp, err := http.Post(conf.redirectURL, "application/json", bytes.NewReader(body))
    if err != nil {
        log.Error(err)
    }
    defer resp.Body.Close()
    log.Info(resp)

    var data json.RawMessage
    if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
        fmt.Println(err)
        return
    }
    helper.SendJsonOk(w, data)
}

Upvotes: 1

Related Questions