Golang HTTPS/TLS POST client/server

15,854

You didn't share the error message, but I assume the client.Post call wasn't allowing a string as its third parameter, because it requires an io.Reader. Try this instead:

out := s + " world"     
resp, err := client.Post(link, "text/plain", bytes.NewBufferString(out))

On the server side, you already have the right code set up to handle the POST request. Just check the method:

http.HandleFunc("/static/", func (w http.ResponseWriter, r *http.Request) {
    if r.Method == "POST" {
        // handle POST requests
    } else {
        // handle all other requests
    }
})

I noticed one other issue. Using index.html probably won't work here. http.ServeFile will redirect that path. See https://golang.org/pkg/net/http/#ServeFile:

As a special case, ServeFile redirects any request where r.URL.Path ends in "/index.html" to the same path, without the final "index.html". To avoid such redirects either modify the path or use ServeContent.

I'd suggest just using a different file name to avoid that issue.

Share:
15,854

Related videos on Youtube

vesche
Author by

vesche

nix geek, programmer, nootropic-popper, wannabe neal stephenson novel character

Updated on May 25, 2022

Comments

  • vesche
    vesche almost 2 years

    I have written a simple client/server in Go that will do an HTTP GET over TLS, but I'm trying to also make it capable of doing an HTTP POST over TLS.

    In the example below index.html just contains the text hello, and the HTTP GET is working fine. I want the client to get the HTTP GET and write back, hello world to the server.

    client

    package main
    
    import (
        "crypto/tls"
        "fmt"
        "io/ioutil"
        "net/http"
        "strings"
    )
    
    func main() {
        link := "https://10.0.0.1/static/index.html"
    
        tr := &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        }
        client := &http.Client{Transport: tr}
        response, err := client.Get(link)
        if err != nil {
            fmt.Println(err)
        }
        defer response.Body.Close()
    
        content, _ := ioutil.ReadAll(response.Body)
        s := strings.TrimSpace(string(content))
    
        fmt.Println(s)
    
        // out := s + " world"      
        // Not working POST...
        // resp, err := client.Post(link, "text/plain", &out)
    
    }
    

    server

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
    )
    
    func main() {
        http.HandleFunc("/static/", func (w http.ResponseWriter, r *http.Request) {
            fmt.Println("Got connection!")
            http.ServeFile(w, r, r.URL.Path[1:])
        })
        log.Fatal(http.ListenAndServeTLS(":443", "server.crt", "server.key", nil))
    }
    

    I also currently have nothing to handle the POST on the server side, but I just want it to print it out to the screen so when I run the client I will see the server print hello world.

    How should I fix my client code to do a proper POST? And what should the corresponding server code look like to accept the POST? Any help would be appreciated, I'm having trouble finding HTTPS/TLS POST examples.

    • Marsel Novy
      Marsel Novy over 7 years
      You need to add CA of your certificate to your transport like
    • vesche
      vesche over 7 years
      @MarcelNovy I'm using a self-signed certificate... That doesn't have anything to do with my question.
    • superfell
      superfell over 7 years
      It would be useful if you mentioned how your current attempt at POST doesn't work.