0

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

1 Answer 1

1

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)
}
Sign up to request clarification or add additional context in comments.

9 Comments

Hi @mkopriva, that worked, I am receiving the response I needed from the other service, however now when I send it back to my initial request from postman I do not receive it. Why might this be?
@Marius if I understand your problem correctly the issue is with the SendJsonOk function and the fact that you're passing resp directly as the second argument. I'll edit the answer to add a fix for that.
@Marius I've updated the example code, try it out and let me know if it works now. Note also that I've added defer resp.Body.Close(), this is important, if you don't close response bodies you'll leak memory.
Thank you for your response, but now for some reason the original request does not get my response. I logged the response body from the redirected request and I receive the data I needed. however when I write the response to the initial request. I receive Could not get response. Error: socket hang up I tried a lot of code variations, but for some reason my Postman request does not get the needed response.
@Marius please update the question by adding the new handler code that you're running, and do not leave out any details, they may be important. Also add a comment to the line of code that is causing the error so that I know exactly where it's coming from.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.