2

I'm trying to read from request then use that result to do POST request to another endpoint then process its results then return its results in JSON.

I have below code so far:

// POST 
func (u *UserResource) authenticate(request *restful.Request, response *restful.Response) {
    Api := Api{url: "http://api.com/api"}
    usr := new(User)
    err := request.ReadEntity(&usr)
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }

    api_resp, err := http.Post(Api.url, "text/plain", bytes.NewBuffer(usr))
    if err != nil {
        response.WriteErrorString(http.StatusInternalServerError, err.Error())
        return
    }
    defer api_resp.Body.Close()
    body, err := ioutil.ReadAll(api_resp.Body)
    response.WriteHeader(http.StatusCreated)
    err = xml.Unmarshal(body, usr)
    if err != nil {
        fmt.Printf("error: %v", err)
        return
    }
//  result, err := json.Marshal(usr)
//  response.Write(result)
    response.WriteEntity(&usr)
    fmt.Printf("Name: %q\n", usr.UserName)
}

I'm using Go Restful package for Writes and Reads.

I'm getting this error when I compile the file:

src\login.go:59: cannot use usr (type *User) as type []byte in argument to bytes.NewBuffer

What would be the best way to solve this issue so I can do a POST with payload correctly?

Passionate Engineer
  • 10,034
  • 26
  • 96
  • 168
  • possible duplicate of [Go - how do I dump the struct into the byte array without reflection?](http://stackoverflow.com/questions/12854125/go-how-do-i-dump-the-struct-into-the-byte-array-without-reflection) – Alex Netkachov Sep 17 '14 at 14:37
  • @DewyBroto How can I encode it in XML then change to `[]byte` format for sending as POST? I tried Print with request.Request.Body but it's outputting nothing... – Passionate Engineer Sep 17 '14 at 15:19
  • @DewyBroto I think the problem is `ReadEntity` as when I do `fmt.Println` to print out `usr.UserName` for example it prints out `nil` – Passionate Engineer Sep 17 '14 at 15:29

2 Answers2

1

You need to marshal your data structure to slice of bytes. Something like this:

usrXmlBytes, err := xml.Marshal(usr)
if err != nil {
    response.WriteErrorString(http.StatusInternalServerError, err.Error())
    return
}
api_resp, err := http.Post(Api.url, "text/plain", bytes.NewReader(usrXmlBytes))
Simon Fox
  • 5,995
  • 1
  • 18
  • 22
RoninDev
  • 5,446
  • 3
  • 23
  • 37
  • If you need json serialization, use `encoding/json` instead of `encoding/xml` – RoninDev Sep 17 '14 at 15:07
  • I need to get JSON request from client and convert it into XML then do a POST request to another end point. Then I need to re-parse the results into JSON then write back to the client – Passionate Engineer Sep 17 '14 at 15:16
  • I tried and it doesn't work. It seems like ReadEntity doesn't work properly as I did usr.Token but came with no results but when I manually added string valid XML instead of `bytes.NewBuffer(usr)` it works somehow – Passionate Engineer Sep 17 '14 at 15:28
  • maybe because usr is a pointer already? Try that: `err := request.ReadEntity(usr)` – RoninDev Sep 17 '14 at 15:32
  • Yes it works! But I just found out that `ioutil.ReadAll` returns something like this `\n \n\n ` How do I make it so it doesn't escape but encode properly in XML? – Passionate Engineer Sep 17 '14 at 15:46
  • I do not understand what exactly you mean. How you got that output? – RoninDev Sep 17 '14 at 16:23
  • Actually sorry this is correct. I just need to manipulate JSON payload into valid XML structure before doing a POST request to another endpoint. – Passionate Engineer Sep 17 '14 at 16:30
0

http.Post takes an io.Reader as the third argument. You could implement io.Reader on your User type or more simply serialize your data and use the bytes pkg to to implement io.Reader

b, err := json.Marshal(usr)
if err != nil {
    response.WriteErrorString(http.StatusInternalServerError, err.Error())
    return
}
api_resp, err := http.Post(Api.url, "text/plain", bytes.NewReader(b))
jmaloney
  • 11,580
  • 2
  • 36
  • 29