init
This commit is contained in:
136
checks.go
Normal file
136
checks.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package watchdog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultTimeout is used to limit checks duration
|
||||
const DefaultTimeout = time.Second * 10
|
||||
|
||||
// GetHTTP creates a CheckFunc that operates as follows.
|
||||
// The check calls GET method for provided addr using http.DefaultClient.
|
||||
// If request fails within specified timeout the returned status is StatusDown.
|
||||
// The function then tries to read response body. If it fails,
|
||||
// the returned status is StatusDown.
|
||||
// If request secceeds but reponse code is not 200, the returned
|
||||
// status is StatusPartiallyAvailable and response body is contained in the
|
||||
// returned error.
|
||||
//
|
||||
// GetHTTP return an error if addr can not be parsed with url.Parse.
|
||||
// If zero timeout is provided then the DefaultTimeout (10 second) is used.
|
||||
func GetHTTP(addr string, timeout time.Duration) (CheckFunc, error) {
|
||||
u, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("coulf not parse URL: %w", err)
|
||||
}
|
||||
|
||||
if timeout == 0 {
|
||||
timeout = DefaultTimeout
|
||||
}
|
||||
|
||||
return func(ctx context.Context) (Status, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return StatusUnknown, fmt.Errorf("failed to create http request: %w", err)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return StatusDown, fmt.Errorf("do request failed: %w", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return StatusDown, fmt.Errorf("err reading response body: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return StatusDown, fmt.Errorf("got HTTP response code %d, body: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
return StatusOK, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HeadHTTP creates a CheckFunc that operates as follows.
|
||||
// The check calls GET method for provided addr using http.DefaultClient.
|
||||
// If request fails within specified timeout the returned status is StatusDown.
|
||||
//
|
||||
// If request secceeds but reponse code is not 200, the returned
|
||||
// status is StatusPartiallyAvailable.
|
||||
//
|
||||
// HeadHTTP return an error if addr can not be parsed with url.Parse.
|
||||
// If zero timeout is provided then the DefaultTimeout (10 second) is used.
|
||||
func HeadHTTP(addr string, timeout time.Duration) (CheckFunc, error) {
|
||||
u, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("coulf not parse URL: %w", err)
|
||||
}
|
||||
|
||||
if timeout == 0 {
|
||||
timeout = DefaultTimeout
|
||||
}
|
||||
|
||||
return func(ctx context.Context) (Status, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodHead, u.String(), nil)
|
||||
if err != nil {
|
||||
return StatusUnknown, fmt.Errorf("failed to create http request: %w", err)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return StatusDown, fmt.Errorf("do request failed: %w", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return StatusDown, fmt.Errorf("got HTTP response code %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return http.StatusOK, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DialTCP creates a CheckFunc that may be used to check tcp connectivity
|
||||
// to a host.
|
||||
// The check tries to net.DialTimeout to the provided addr. If it fails,
|
||||
// the returned status is StatusDown.
|
||||
//
|
||||
// No validation of addr is made.
|
||||
// If zero timeout is provided then the DefaultTimeout (10 second) is used.
|
||||
func DialTCP(addr string, timeout time.Duration) (CheckFunc, error) {
|
||||
if timeout == 0 {
|
||||
timeout = DefaultTimeout
|
||||
}
|
||||
|
||||
return func(ctx context.Context) (Status, error) {
|
||||
deadline := time.Now().Add(timeout)
|
||||
if t, ok := ctx.Deadline(); ok && t.Before(deadline) {
|
||||
deadline = t
|
||||
}
|
||||
|
||||
conn, err := net.DialTimeout("tcp", addr, time.Until(deadline))
|
||||
if err != nil {
|
||||
return StatusDown, fmt.Errorf("error dialing: %w", err)
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
return StatusOK, nil
|
||||
}, nil
|
||||
}
|
Reference in New Issue
Block a user