diff --git a/internal/assets/templates/monitor.html b/internal/assets/templates/monitor.html index e618f8b..0333741 100644 --- a/internal/assets/templates/monitor.html +++ b/internal/assets/templates/monitor.html @@ -22,13 +22,13 @@ {{ define "site" }} {{ if .IconUrl }} - + {{ end }}
- {{ .Title }} + {{ .Title }}
-{{ if eq .StatusStyle "good" }} +{{ if eq .StatusStyle "ok" }}
diff --git a/internal/feed/monitor.go b/internal/feed/monitor.go index e08964f..03cdcf4 100644 --- a/internal/feed/monitor.go +++ b/internal/feed/monitor.go @@ -7,6 +7,11 @@ import ( "time" ) +type SiteStatusRequest struct { + URL string `yaml:"url"` + AllowInsecure bool `yaml:"allow-insecure"` +} + type SiteStatus struct { Code int TimedOut bool @@ -14,14 +19,28 @@ type SiteStatus struct { Error error } -func getSiteStatusTask(request *http.Request) (SiteStatus, error) { +func getSiteStatusTask(statusRequest *SiteStatusRequest) (SiteStatus, error) { + request, err := http.NewRequest(http.MethodGet, statusRequest.URL, nil) + + if err != nil { + return SiteStatus{ + Error: err, + }, nil + } + ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() request = request.WithContext(ctx) - start := time.Now() - response, err := http.DefaultClient.Do(request) - took := time.Since(start) - status := SiteStatus{ResponseTime: took} + requestSentAt := time.Now() + var response *http.Response + + if !statusRequest.AllowInsecure { + response, err = defaultClient.Do(request) + } else { + response, err = defaultInsecureClient.Do(request) + } + + status := SiteStatus{ResponseTime: time.Since(requestSentAt)} if err != nil { if errors.Is(err, context.DeadlineExceeded) { @@ -29,7 +48,7 @@ func getSiteStatusTask(request *http.Request) (SiteStatus, error) { } status.Error = err - return status, err + return status, nil } defer response.Body.Close() @@ -39,7 +58,7 @@ func getSiteStatusTask(request *http.Request) (SiteStatus, error) { return status, nil } -func FetchStatusesForRequests(requests []*http.Request) ([]SiteStatus, error) { +func FetchStatusForSites(requests []*SiteStatusRequest) ([]SiteStatus, error) { job := newJob(getSiteStatusTask, requests).withWorkers(20) results, _, err := workerPoolDo(job) diff --git a/internal/feed/requests.go b/internal/feed/requests.go index 0f49ff0..3ce5d9f 100644 --- a/internal/feed/requests.go +++ b/internal/feed/requests.go @@ -2,6 +2,7 @@ package feed import ( "context" + "crypto/tls" "encoding/json" "encoding/xml" "fmt" @@ -11,8 +12,19 @@ import ( "time" ) +const defaultClientTimeout = 5 * time.Second + var defaultClient = &http.Client{ - Timeout: 5 * time.Second, + Timeout: defaultClientTimeout, +} + +var insecureClientTransport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, +} + +var defaultInsecureClient = &http.Client{ + Timeout: defaultClientTimeout, + Transport: insecureClientTransport, } type RequestDoer interface { diff --git a/internal/widget/monitor.go b/internal/widget/monitor.go index c4d78f8..7216e9c 100644 --- a/internal/widget/monitor.go +++ b/internal/widget/monitor.go @@ -2,9 +2,7 @@ package widget import ( "context" - "fmt" "html/template" - "net/http" "strconv" "time" @@ -37,22 +35,23 @@ func statusCodeToText(status int) string { func statusCodeToStyle(status int) string { if status == 200 { - return "good" + return "ok" } - return "bad" + return "error" } type Monitor struct { widgetBase `yaml:",inline"` Sites []struct { - Title string `yaml:"title"` - Url OptionalEnvString `yaml:"url"` - IconUrl string `yaml:"icon"` - SameTab bool `yaml:"same-tab"` - Status *feed.SiteStatus `yaml:"-"` - StatusText string `yaml:"-"` - StatusStyle string `yaml:"-"` + *feed.SiteStatusRequest `yaml:",inline"` + Status *feed.SiteStatus `yaml:"-"` + Title string `yaml:"title"` + IconUrl string `yaml:"icon"` + IsSimpleIcon bool `yaml:"-"` + SameTab bool `yaml:"same-tab"` + StatusText string `yaml:"-"` + StatusStyle string `yaml:"-"` } `yaml:"sites"` Style string `yaml:"style"` } @@ -60,25 +59,21 @@ type Monitor struct { func (widget *Monitor) Initialize() error { widget.withTitle("Monitor").withCacheDuration(5 * time.Minute) + for i := range widget.Sites { + widget.Sites[i].IconUrl, widget.Sites[i].IsSimpleIcon = toSimpleIconIfPrefixed(widget.Sites[i].IconUrl) + } + return nil } func (widget *Monitor) Update(ctx context.Context) { - requests := make([]*http.Request, len(widget.Sites)) + requests := make([]*feed.SiteStatusRequest, len(widget.Sites)) for i := range widget.Sites { - request, err := http.NewRequest("GET", string(widget.Sites[i].Url), nil) - - if err != nil { - message := fmt.Errorf("failed to create http request for %s: %s", widget.Sites[i].Url, err) - widget.withNotice(message) - continue - } - - requests[i] = request + requests[i] = widget.Sites[i].SiteStatusRequest } - statuses, err := feed.FetchStatusesForRequests(requests) + statuses, err := feed.FetchStatusForSites(requests) if !widget.canContinueUpdateAfterHandlingErr(err) { return