Home > Blockchain >  HTTPS for Golang API
HTTPS for Golang API

Time:04-25

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. I tried a few tutorials online to configure Apache to listen on 8080 using the SSL keys, but without success.

I did set to listen on port 8443 in ports.conf:

Listen 80

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

and this is the VirtualHost for 80 (non SSL) and 8443 (SSL):

<VirtualHost *:80>
        ServerAdmin [email protected]
        ServerName www.example.com
        ServerAlias example.com
        DocumentRoot /var/www/html/example/public_html/

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        RewriteEngine on
        RewriteCond %{SERVER_NAME} =www.example.com [OR]
        RewriteCond %{SERVER_NAME} =example.com
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<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>

Calling it on 8443 gives me

The server encountered an internal error or misconfiguration and was unable to complete your request.

I can call the API at https://www.example.com:8080/hello.

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))
}

CodePudding user response:

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)
}

CodePudding user response:

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
}
  • Related