123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- package httpsslserver
- import (
- "context"
- "crypto"
- "crypto/tls"
- "crypto/x509"
- "errors"
- "fmt"
- "github.com/SongZihuan/Http-Demo/src/certssl"
- "github.com/SongZihuan/Http-Demo/src/engine"
- "github.com/SongZihuan/Http-Demo/src/flagparser"
- "net/http"
- "sync"
- "time"
- )
- var HttpSSLServer *http.Server = nil
- var HttpSSLAddress string
- var HttpSSLDomain string
- var HttpSSLEmail string
- var HttpSSLCertDir string
- var PrivateKey crypto.PrivateKey
- var Certificate *x509.Certificate
- var ErrStop = fmt.Errorf("http server error")
- var ReloadMutex sync.Mutex
- func InitHttpSSLServer() (err error) {
- HttpSSLAddress = flagparser.HttpsAddress
- HttpSSLDomain = flagparser.HttpsDomain
- HttpSSLEmail = flagparser.HttpsEmail
- HttpSSLCertDir = flagparser.HttpsCertDir
- PrivateKey, Certificate, err = certssl.GetCertificateAndPrivateKey(HttpSSLCertDir, HttpSSLEmail, HttpSSLAddress, HttpSSLDomain)
- if err != nil {
- return err
- }
- return initHttpSSLServer()
- }
- func initHttpSSLServer() (err error) {
- tlsConfig := &tls.Config{
- Certificates: []tls.Certificate{{
- Certificate: [][]byte{Certificate.Raw}, // Raw包含 DER 编码的证书
- PrivateKey: PrivateKey,
- Leaf: Certificate,
- }},
- }
- HttpSSLServer = &http.Server{
- Addr: HttpSSLAddress,
- Handler: engine.Engine,
- TLSConfig: tlsConfig,
- }
- return nil
- }
- func RunServer() error {
- stopchan := make(chan bool)
- WatchCert(stopchan)
- err := runServer()
- stopchan <- true
- return err
- }
- func runServer() error {
- fmt.Printf("https server start at %s\n", HttpSSLAddress)
- ListenCycle:
- for {
- err := HttpSSLServer.ListenAndServeTLS("", "")
- if err != nil && errors.Is(err, http.ErrServerClosed) {
- if ReloadMutex.TryLock() {
- ReloadMutex.Unlock()
- return ErrStop
- }
- ReloadMutex.Lock()
- ReloadMutex.Unlock() // 等待证书更换完毕
- continue ListenCycle
- } else if err != nil {
- return err
- }
- }
- }
- func WatchCert(stopchan chan bool) {
- newchan := make(chan certssl.NewCert)
- go func() {
- err := certssl.WatchCertificateAndPrivateKey(HttpSSLCertDir, HttpSSLEmail, HttpSSLAddress, HttpSSLDomain, PrivateKey, Certificate, stopchan, newchan)
- if err != nil {
- fmt.Printf("watch cert error: %s", err.Error())
- }
- }()
- go func() {
- select {
- case res := <-newchan:
- if res.Certificate == nil && res.PrivateKey == nil && res.Error == nil {
- close(newchan)
- return
- } else if res.Error != nil {
- fmt.Printf("watch cert error: %s", res.Error.Error())
- } else if res.PrivateKey == nil && res.Certificate == nil {
- func() {
- ReloadMutex.Lock()
- defer ReloadMutex.Unlock()
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
- defer cancel()
- err := HttpSSLServer.Shutdown(ctx)
- if err != nil {
- fmt.Printf("reload error: %s", err.Error())
- }
- PrivateKey = res.PrivateKey
- Certificate = res.Certificate
- }()
- }
- }
- }()
- }
|