diff --git a/internal/api/v1/certapi/cert_info.go b/internal/api/v1/certapi/cert_info.go new file mode 100644 index 0000000..07edfd9 --- /dev/null +++ b/internal/api/v1/certapi/cert_info.go @@ -0,0 +1,41 @@ +package certapi + +import ( + "encoding/json" + "net/http" + + config "github.com/yusing/go-proxy/internal/config/types" +) + +type CertInfo struct { + Subject string `json:"subject"` + Issuer string `json:"issuer"` + NotBefore int64 `json:"not_before"` + NotAfter int64 `json:"not_after"` + DNSNames []string `json:"dns_names"` + EmailAddresses []string `json:"email_addresses"` +} + +func GetCertInfo(w http.ResponseWriter, r *http.Request) { + autocert := config.GetInstance().AutoCertProvider() + if autocert == nil { + http.Error(w, "autocert is not enabled", http.StatusNotFound) + return + } + + cert, err := autocert.GetCert(nil) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + certInfo := CertInfo{ + Subject: cert.Leaf.Subject.CommonName, + Issuer: cert.Leaf.Issuer.CommonName, + NotBefore: cert.Leaf.NotBefore.Unix(), + NotAfter: cert.Leaf.NotAfter.Unix(), + DNSNames: cert.Leaf.DNSNames, + EmailAddresses: cert.Leaf.EmailAddresses, + } + json.NewEncoder(w).Encode(&certInfo) +} diff --git a/internal/api/v1/certapi/renew.go b/internal/api/v1/certapi/renew.go new file mode 100644 index 0000000..bb993f9 --- /dev/null +++ b/internal/api/v1/certapi/renew.go @@ -0,0 +1,56 @@ +package certapi + +import ( + "net/http" + + config "github.com/yusing/go-proxy/internal/config/types" + "github.com/yusing/go-proxy/internal/gperr" + "github.com/yusing/go-proxy/internal/logging" + "github.com/yusing/go-proxy/internal/logging/memlogger" + "github.com/yusing/go-proxy/internal/net/gphttp/gpwebsocket" +) + +func RenewCert(w http.ResponseWriter, r *http.Request) { + autocert := config.GetInstance().AutoCertProvider() + if autocert == nil { + http.Error(w, "autocert is not enabled", http.StatusNotFound) + return + } + + conn, err := gpwebsocket.Initiate(w, r) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + //nolint:errcheck + defer conn.CloseNow() + + logs, cancel := memlogger.Events() + defer cancel() + + done := make(chan struct{}) + + go func() { + defer close(done) + err = autocert.ObtainCert() + if err != nil { + gperr.LogError("failed to obtain cert", err) + gpwebsocket.WriteText(r, conn, err.Error()) + } else { + logging.Info().Msg("cert obtained successfully") + } + }() + for { + select { + case l := <-logs: + if err != nil { + return + } + if !gpwebsocket.WriteText(r, conn, string(l)) { + return + } + case <-done: + return + } + } +}