• With issues:
  • Use the search tool before opening a new issue.
  • Please provide source code and commit sha if you found a bug.
  • Review existing issues and provide feedback or react to them.

Description

Consider the following code to start the HTTPS server:

route := gin.New()
route.RunTLS(addr, tlsCert, tlsKey)

Is there any way to reload the TLS cert? I have looked through the doc and searched the internet but failed to find the answer.

Is it possible to have something like this to reload the cert when cert is changed

route.reloadTLS(tlsCert, tlsKey)

I can contribute if it is reasonable and not hard to implement

Expectations

Actual result

Environment

  • go version:
  • gin version (or commit ref): v1.9.1
  • operating system:

Comment From: zanmato

You have to start the server yourself via ListendAndServeTLS instead of using the RunTLS func of the gin engine. Then you can pass your own tls.Config and implement GetCertificate to reload the certificate. See https://pkg.go.dev/crypto/tls#Config

Comment From: shiyuhang0

@zanmato sorry i miss the reply. GetCertificate may works, but it will be called every time a request comes. Is there any way to reload cert regularly?I only need to reload before it expired and don't want to restart service

Comment From: shiyuhang0

I use GetCertificate and cache the cert to solve the problem. Here is a demo:

func main() {
    route := gin.Default()
    beta := route.Group("/api")
    beta.POST("/test", TLSTest)

    addr := ":443"
    certFile := "/Users/shiyuhang/github/godemo/http/tls.crt"
    keyFile := "/Users/shiyuhang/github/godemo/http/tls.key"

    cert, err := tls.LoadX509KeyPair(certFile, keyFile)
    server := &http.Server{Addr: addr, Handler: route.Handler()}
    server.TLSConfig = &tls.Config{
        GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
            return &cert, nil
        },
    }

    go reloadCert(certFile, keyFile, &cert)
    err = server.ListenAndServeTLS("", "")
    if err != nil {
        println(err.Error())
    }
}

func reloadCert(certFile, keyFile string, cert *tls.Certificate) {
    ticker := time.NewTicker(20 * time.Second)
    for {
        select {
        case <-ticker.C:
            crt, err := tls.LoadX509KeyPair(certFile, keyFile)
            if err != nil {
                println("load cert error")
            } else {
                println("load cert success")
                *cert = crt
            }
        }
    }
}