• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

joohoi / acme-dns / 21712085685

05 Feb 2026 12:48PM UTC coverage: 77.229% (+4.0%) from 73.276%
21712085685

Pull #325

github

web-flow
Merge 22c41911c into b7a0a8a7b
Pull Request #325: Refactoring

582 of 764 new or added lines in 20 files covered. (76.18%)

3 existing lines in 1 file now uncovered.

797 of 1032 relevant lines covered (77.23%)

7.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

26.67
/pkg/api/api.go
1
package api
2

3
import (
4
        "context"
5
        "crypto/tls"
6
        "net/http"
7
        "time"
8

9
        "github.com/joohoi/acme-dns/pkg/acmedns"
10

11
        "github.com/caddyserver/certmagic"
12
        "github.com/julienschmidt/httprouter"
13
        "github.com/rs/cors"
14
        "go.uber.org/zap"
15
)
16

17
type AcmednsAPI struct {
18
        Config  *acmedns.AcmeDnsConfig
19
        DB      acmedns.AcmednsDB
20
        Logger  *zap.SugaredLogger
21
        errChan chan error
22
}
23

24
func Init(config *acmedns.AcmeDnsConfig, db acmedns.AcmednsDB, logger *zap.SugaredLogger, errChan chan error) AcmednsAPI {
14✔
25
        a := AcmednsAPI{Config: config, DB: db, Logger: logger, errChan: errChan}
14✔
26
        return a
14✔
27
}
14✔
28

NEW
29
func (a *AcmednsAPI) Start(dnsservers []acmedns.AcmednsNS) {
×
NEW
30
        var err error
×
NEW
31
        //TODO: do we want to debug log the HTTP server?
×
NEW
32
        stderrorlog, err := zap.NewStdLogAt(a.Logger.Desugar(), zap.ErrorLevel)
×
NEW
33
        if err != nil {
×
NEW
34
                a.errChan <- err
×
NEW
35
                return
×
NEW
36
        }
×
NEW
37
        api := httprouter.New()
×
NEW
38
        c := cors.New(cors.Options{
×
NEW
39
                AllowedOrigins:     a.Config.API.CorsOrigins,
×
NEW
40
                AllowedMethods:     []string{"GET", "POST"},
×
NEW
41
                OptionsPassthrough: false,
×
NEW
42
                Debug:              a.Config.General.Debug,
×
NEW
43
        })
×
NEW
44
        if a.Config.General.Debug {
×
NEW
45
                // Logwriter for saner log output
×
NEW
46
                c.Log = stderrorlog
×
NEW
47
        }
×
NEW
48
        if !a.Config.API.DisableRegistration {
×
NEW
49
                api.POST("/register", a.webRegisterPost)
×
NEW
50
        }
×
NEW
51
        api.POST("/update", a.Auth(a.webUpdatePost))
×
NEW
52
        api.GET("/health", a.healthCheck)
×
NEW
53

×
NEW
54
        host := a.Config.API.IP + ":" + a.Config.API.Port
×
NEW
55

×
NEW
56
        // TLS specific general settings
×
NEW
57
        cfg := &tls.Config{
×
NEW
58
                MinVersion: tls.VersionTLS12,
×
NEW
59
        }
×
NEW
60

×
NEW
61
        switch a.Config.API.TLS {
×
NEW
62
        case acmedns.ApiTlsProviderLetsEncrypt, acmedns.ApiTlsProviderLetsEncryptStaging:
×
NEW
63
                magic := a.setupTLS(dnsservers)
×
NEW
64
                err = magic.ManageAsync(context.Background(), []string{a.Config.General.Domain})
×
NEW
65
                if err != nil {
×
NEW
66
                        a.errChan <- err
×
NEW
67
                        return
×
NEW
68
                }
×
NEW
69
                cfg.GetCertificate = magic.GetCertificate
×
NEW
70
                srv := &http.Server{
×
NEW
71
                        Addr:         host,
×
NEW
72
                        Handler:      c.Handler(api),
×
NEW
73
                        TLSConfig:    cfg,
×
NEW
74
                        ErrorLog:     stderrorlog,
×
NEW
75
                        ReadTimeout:  5 * time.Second,
×
NEW
76
                        WriteTimeout: 10 * time.Second,
×
NEW
77
                        IdleTimeout:  120 * time.Second,
×
NEW
78
                }
×
NEW
79
                a.Logger.Infow("Listening HTTPS",
×
NEW
80
                        "host", host,
×
NEW
81
                        "domain", a.Config.General.Domain)
×
NEW
82
                err = srv.ListenAndServeTLS("", "")
×
NEW
83
        case acmedns.ApiTlsProviderCert:
×
NEW
84
                srv := &http.Server{
×
NEW
85
                        Addr:         host,
×
NEW
86
                        Handler:      c.Handler(api),
×
NEW
87
                        TLSConfig:    cfg,
×
NEW
88
                        ErrorLog:     stderrorlog,
×
NEW
89
                        ReadTimeout:  5 * time.Second,
×
NEW
90
                        WriteTimeout: 10 * time.Second,
×
NEW
91
                        IdleTimeout:  120 * time.Second,
×
NEW
92
                }
×
NEW
93
                a.Logger.Infow("Listening HTTPS",
×
NEW
94
                        "host", host,
×
NEW
95
                        "domain", a.Config.General.Domain)
×
NEW
96
                err = srv.ListenAndServeTLS(a.Config.API.TLSCertFullchain, a.Config.API.TLSCertPrivkey)
×
NEW
97
        default:
×
NEW
98
                a.Logger.Infow("Listening HTTP",
×
NEW
99
                        "host", host)
×
NEW
100
                err = http.ListenAndServe(host, c.Handler(api))
×
101
        }
NEW
102
        if err != nil {
×
NEW
103
                a.errChan <- err
×
NEW
104
        }
×
105
}
106

107
func (a *AcmednsAPI) setupTLS(dnsservers []acmedns.AcmednsNS) *certmagic.Config {
2✔
108
        provider := NewChallengeProvider(dnsservers)
2✔
109
        certmagic.Default.Logger = a.Logger.Desugar()
2✔
110
        storage := certmagic.FileStorage{Path: a.Config.API.ACMECacheDir}
2✔
111

2✔
112
        // Set up certmagic for getting certificate for acme-dns api
2✔
113
        certmagic.DefaultACME.DNS01Solver = &provider
2✔
114
        certmagic.DefaultACME.Agreed = true
2✔
115
        certmagic.DefaultACME.Logger = a.Logger.Desugar()
2✔
116
        if a.Config.API.TLS == acmedns.ApiTlsProviderLetsEncrypt {
3✔
117
                certmagic.DefaultACME.CA = certmagic.LetsEncryptProductionCA
1✔
118
        } else {
2✔
119
                certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA
1✔
120
        }
1✔
121
        certmagic.DefaultACME.Email = a.Config.API.NotificationEmail
2✔
122

2✔
123
        magicConf := certmagic.Default
2✔
124
        magicConf.Logger = a.Logger.Desugar()
2✔
125
        magicConf.Storage = &storage
2✔
126
        magicConf.DefaultServerName = a.Config.General.Domain
2✔
127
        magicCache := certmagic.NewCache(certmagic.CacheOptions{
2✔
128
                GetConfigForCert: func(cert certmagic.Certificate) (*certmagic.Config, error) {
2✔
NEW
129
                        return &magicConf, nil
×
NEW
130
                },
×
131
                Logger: a.Logger.Desugar(),
132
        })
133
        magic := certmagic.New(magicCache, magicConf)
2✔
134
        return magic
2✔
135
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc