Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XML HTTP Post in Go

Tags:

xml

go

I'm attempting to create a post request that uses xml.

I know I need to use:

http.Post("myurl", "text/xml", body)

But the thing I can't figure out is how to set the actual XML data to be sent.

<request>
    <parameters>
        <email>[email protected]</email>
        <password>test</password>
    </parameters>
</request>

And setting a header to have Content-Type: text/xml

like image 926
Mike Avatar asked Dec 02 '22 17:12

Mike


2 Answers

No need to make your own request or manually set the content type, it can all be done with a single simple http.Post call:

package main

import (
    "log"
    "net/http"
    "strings"
)

func main() {
    const myurl = "http://127.0.0.1:8080"
    const xmlbody = `
<request>
    <parameters>
        <email>[email protected]</email>
        <password>test</password>
    </parameters>
</request>`

    resp, err := http.Post(myurl, "text/xml", strings.NewReader(xmlbody))
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    // Do something with resp.Body
}

Whatever you use for the bodyType argument goes into the content type header. The server will see:

POST / HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Go 1.1 package http
Content-Length: 127
Content-Type: text/xml
Accept-Encoding: gzip


<request>
    <parameters>
        <email>[email protected]</email>
        <password>test</password>
    </parameters>
</request>

(The extra blank line is because I chose to start the string literal on a new line).

like image 117
Dave C Avatar answered Dec 12 '22 10:12

Dave C


I am also new to Go, but I'd take a brave trial and try to answer this.

You can use http.Client with http.NewRequest, then set the request header before sending the POST, working sample like this:

package main

import (
    "bytes"
    "fmt"
    "net/http"
)

func main() {
    // or you can use []byte(`...`) and convert to Buffer later on
    body := "<request> <parameters> <email>[email protected]</email> <password>test</password> </parameters> </request>"

    client := &http.Client{}
    // build a new request, but not doing the POST yet
    req, err := http.NewRequest("POST", "http://localhost:8080/", bytes.NewBuffer([]byte(body)))
    if err != nil {
        fmt.Println(err)
    }
    // you can then set the Header here
    // I think the content-type should be "application/xml" like json...
    req.Header.Add("Content-Type", "application/xml; charset=utf-8")
    // now POST it
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(resp)
}

Response from Client (dummy server so bad response of course):

>>> go run xmlpost.go
Post http://localhost:8080/: dial tcp 127.0.0.1:8080: connection refused
<nil>

Server Response:

>>> ncat -l 8080
POST / HTTP/1.1
Host: localhost:8080
User-Agent: Go 1.1 package http
Content-Length: 102
Content-Type: application/xml; charset=utf-8
Accept-Encoding: gzip

<request> <parameters> <email>[email protected]</email> <password>test</password> </parameters> </request>

update:

Thanks for @DaveC pointing out the unnecessary io.Reader(...), and apologized for using # for comment, I'm too used to Python and it came natural when adding comment in SO. Now fixed.

like image 23
Anzel Avatar answered Dec 12 '22 08:12

Anzel