skip to Main Content

I am new to Golang and I did set up a "hello world!" test message for a Golang API on our VPS. It works just fine at http://www.example.com:8080/hello. I would like however to move to HTTPS.

Could someone tell me step by step the right procedure to go from HTTP to HTTPS for a golang API? Thank you!

In case there is an issue with the golang code:

package main

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

func main() {
        http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
                fmt.Fprintf(w, "Hello, World")
        })

        fmt.Println("Server Started On Port 8080")
        log.Fatal(http.ListenAndServe(":8080", nil))
}

3

Answers


  1. Chosen as BEST ANSWER

    Thanks to John Hanley for support that lead to this answer. First of all I did set the port 8443 for https by editing /etc/apache2/ports.conf:

    Listen 80
    
    <IfModule ssl_module>
            Listen 443
            Listen 8443
    </IfModule>
    

    Then I added a VirtualHost in the config of the example.com domain so that port 8443 acts as a proxy:

    <VirtualHost *:8443>
            ServerAdmin [email protected]
            ServerName www.example.com
            ServerAlias example.com
    
            ProxyRequests Off
            <Proxy *>
                    Order deny,allow
                    Allow from all
            </Proxy>
            ProxyPass / http://localhost:8080/
            ProxyPassReverse / http://localhost:8080/
    
            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    
           Include /etc/letsencrypt/options-ssl-apache.conf
           SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
           SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    </VirtualHost>
    

    and you need to load the modules proxy and proxy_http using e2enmod proxy and e2enmod proxy_http. After reloading apache, the API can be called at https://www.example.com:8443/hello.


  2. Use http.ListenAndServeTLS Instead

    https://pkg.go.dev/net/http#ListenAndServeTLS

        package main
    
    import (
            "fmt"
            "log"
            "net/http"
    )
    
    func main() {
            http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
                    fmt.Fprintf(w, "Hello, World")
            })
    
            fmt.Println("Server Started On Port 8080")
            err := http.ListenAndServeTLS(":8080", "cert.pem", "key.pem", nil)
            log.Fatal(err)
    }
    
    Login or Signup to reply.
  3. Adding on to @Dan ‘s answer. A little more complex implementation but enables you to configure it more.

    If you want to use more than 1 set of certs

    certs := []tls.Certificate{}
    for _, cert := range []{"cert1", "cert2"} {
        certSet, err := tls.LoadX509KeyPair(cert+".pem", cert+".key")
        if err != nil {
            return err
        }
        certs = append(certs, certSet)
    }
    

    Create tls config

    cfg := &tls.Config {
        Certificates: certs,
        MinVersion:   tls.VersionTLS12,
    }
    cfg.BuildNameToCertificate()
    server := &http.Server{
        Addr:        ":8080",
        TLSConfig:   cfg,
        IdleTimeout: 30 * time.Second,
    }
    

    Add handler and start server

    http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, World")
    })
    
    err := server.ListenAndServeTLS("", "") // Dont give filename here if giving set of certs in tls config above
    if err != nil {
        return err
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search