tumblr / go-collins

Collins API Client in Go - https://tumblr.github.io/collins
Apache License 2.0
41 stars 10 forks source link

Asset Updating should be sending data in the post body, not the request URI. #28

Open nshalman opened 4 years ago

nshalman commented 4 years ago

Asset Updating should be sending data in the post body, not the request URI.

Assets.Update uses addOptions which

adds the parameters in opt as URL query parameters to s

This seems to fail when trying to send in Lshw and Lldp information:

        lshwFile, err := os.Open("/tmp/lshw.xml")
        if err != nil {
                log.Fatal(err)
        }
        lshw, err := ioutil.ReadAll(lshwFile)

        lldpFile, err := os.Open("/tmp/lldp.xml")
        if err != nil {
                log.Fatal(err)
        }
        lldp, err := ioutil.ReadAll(lldpFile)

        client, _ := collins.NewClient("blake", "admin:first", "http://collins:9000")
        asset, _, _ := client.Assets.Get("tumblrtag1")
        fmt.Printf("%v\n\n", asset)

        opts := collins.AssetUpdateOpts{
                Lshw:       string(lshw),
                Lldp:       string(lldp),
                ChassisTag: "some-chassis-tag",
        }
        resp, err := client.Assets.Update("tumblrtag1", &opts)
        log.Printf("resp: %+v\n", resp)
        if resp.Response != nil {
                log.Printf("resp.Response: %+v\n", resp.Response)
        }
        if err != nil {
                log.Printf("err: %+v\n", err)
        }
2020/01/03 09:31:04 resp: &{Response:0xc000226000 Container:<nil> PreviousPage:0 CurrentPage:0 NextPage:0 TotalResults:0}
2020/01/03 09:31:04 resp.Response: &{Status:414 Request-URI Too Long StatusCode:414 Proto:HTTP/1.1 ProtoMajor:1 ProtoMinor:1 Header:map[] Body:0xc000234040 ContentLength:-1 TransferEncoding:[] Close:true
Uncompressed:false Trailer:map[] Request:0xc0001a0100 TLS:<nil>}
2020/01/03 09:31:04 err: Response with unexpected Content-Type - `' received.

When using curl with the same data files (per the API documentation for Collins) it works just fine:

curl \
  --data-urlencode "lshw@/tmp/lshw.xml" \
  --data-urlencode "lldp@/tmp/lldp.xml" \
  --data-urlencode "CHASSIS_TAG=some-chassis-tag" \
  http://collins:9000/api/asset/tumblrtag1

Let me know if this issue needs further clarification.

Thank you for Collins, go-collins, and your attention.

nshalman commented 4 years ago

It seems that the correct way to encode the data is along the lines of (see https://stackoverflow.com/a/19253970) the following short snippet:

data := url.Values{}
data.Set("lshw", string(lshw))
data.Set("lldp", string(lldp))
data.Set("CHASSIS_TAG", "some-chassis-tag")
body := strings.NewReader(data.Encode())
req, err := http.NewRequest("POST", "http://collins:9000/api/asset/tumblrtag1", body)

Note the use of url.Values{} and calling its Encode() function.

The complete piece of code that worked, though crude and inexpertly written is this:

func intake() {
        lshwFile, err := os.Open("/tmp/lshw.xml")
        if err != nil {
                log.Fatal(err)
        }
        defer lshwFile.Close()
        lshw, err := ioutil.ReadAll(lshwFile)

        lldpFile, err := os.Open("/tmp/lldp.xml")
        if err != nil {
                log.Fatal(err)
        }
        defer lldpFile.Close()
        lldp, err := ioutil.ReadAll(lldpFile)

        data := url.Values{}
        data.Set("lshw", string(lshw))
        data.Set("lldp", string(lldp))
        data.Set("CHASSIS_TAG", "some-chassis-tag")
        body := strings.NewReader(data.Encode())
        req, err := http.NewRequest("POST", "http://collins:9000/api/asset/tumblrtag1", body)
        if err != nil {
                log.Fatal(err)
        }
        req.SetBasicAuth("blake","admin:first")
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

        resp, err := http.DefaultClient.Do(req)
        defer resp.Body.Close()
        log.Printf("resp: %+v\n", resp)
        respbody, err := ioutil.ReadAll(resp.Body)
        log.Printf("resp body: %s\n", respbody)
        if err != nil {
                log.Printf("err: %+v\n", err)
        }
}