140 lines
2.5 KiB
Go
140 lines
2.5 KiB
Go
|
package hosts
|
||
|
|
||
|
import (
|
||
|
"github.com/go-chi/chi"
|
||
|
"github.com/go-chi/render"
|
||
|
"github.com/miekg/dns"
|
||
|
"net/http"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
defaultDuration = 600 * time.Second
|
||
|
)
|
||
|
|
||
|
func EnableAPI(h Provider, r chi.Router) {
|
||
|
a := &api{hosts: h}
|
||
|
|
||
|
r.Route("/hosts", func(sub chi.Router) {
|
||
|
sub.Get("/", a.hostsGet)
|
||
|
sub.Post("/", a.hostsCreate)
|
||
|
sub.Patch("/{domain}", a.hostsUpdate)
|
||
|
sub.Delete("/{domain}", a.hostsDelete)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
type api struct {
|
||
|
hosts Provider
|
||
|
}
|
||
|
|
||
|
// hostsGet handles GET requests on /hosts (list records)
|
||
|
func (a *api) hostsGet(w http.ResponseWriter, r *http.Request) {
|
||
|
hosts, err := a.hosts.List()
|
||
|
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
render.JSON(w, r, hosts)
|
||
|
}
|
||
|
|
||
|
type requestBody struct {
|
||
|
Domain string `json:"domain"`
|
||
|
Type string `json:"type"`
|
||
|
Values []string `json:"values"`
|
||
|
TTL int `json:"ttl"`
|
||
|
}
|
||
|
|
||
|
func (b requestBody) TTLDuration() time.Duration {
|
||
|
if b.TTL > 0 {
|
||
|
return time.Duration(b.TTL) * time.Second
|
||
|
}
|
||
|
|
||
|
return defaultDuration
|
||
|
}
|
||
|
|
||
|
// hostsUpdate handles POST requests on /hosts
|
||
|
func (a *api) hostsCreate(w http.ResponseWriter, r *http.Request) {
|
||
|
var writer Writer
|
||
|
var ok bool
|
||
|
|
||
|
if writer, ok = a.hosts.(Writer); !ok {
|
||
|
w.WriteHeader(http.StatusNotImplemented)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var request requestBody
|
||
|
|
||
|
err := render.DefaultDecoder(r, &request)
|
||
|
|
||
|
if err != nil {
|
||
|
w.WriteHeader(http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var recordType uint16
|
||
|
|
||
|
if recordType, ok = dns.StringToType[request.Type]; !ok {
|
||
|
w.WriteHeader(http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = writer.Set(request.Domain, &Host{
|
||
|
Type: recordType,
|
||
|
Values: request.Values,
|
||
|
TTL: request.TTLDuration(),
|
||
|
})
|
||
|
|
||
|
if err != nil {
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// hostsUpdate handles PATCH requests on /hosts/:domain
|
||
|
func (a *api) hostsUpdate(w http.ResponseWriter, r *http.Request) {
|
||
|
domain := chi.URLParam(r, "domain")
|
||
|
|
||
|
if domain == "" {
|
||
|
w.WriteHeader(http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var writer Writer
|
||
|
var ok bool
|
||
|
|
||
|
if writer, ok = a.hosts.(Writer); !ok {
|
||
|
w.WriteHeader(http.StatusNotImplemented)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// TODO: Read record from provider, update data from body, save
|
||
|
err := writer.Set(domain, nil)
|
||
|
|
||
|
if err != nil {
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// hostsDelete handles DELETE requests on /hosts/:domain
|
||
|
func (a *api) hostsDelete(w http.ResponseWriter, r *http.Request) {
|
||
|
domain := chi.URLParam(r, "domain")
|
||
|
|
||
|
if domain == "" {
|
||
|
w.WriteHeader(http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var writer Writer
|
||
|
var ok bool
|
||
|
|
||
|
if writer, ok = a.hosts.(Writer); !ok {
|
||
|
w.WriteHeader(http.StatusNotImplemented)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err := writer.Delete(domain)
|
||
|
|
||
|
if err != nil {
|
||
|
|
||
|
}
|
||
|
}
|