summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/httpcheck/cookiejar.go
blob: 628867caa404d72fa18ad1fa764bf059e133149c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// SPDX-License-Identifier: GPL-3.0-or-later

package httpcheck

import (
	"bufio"
	"fmt"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"golang.org/x/net/publicsuffix"
)

// TODO: implement proper cookie auth support
// relevant forum topic: https://community.netdata.cloud/t/howto-http-endpoint-collector-with-cookie-and-user-pass/3981/5?u=ilyam8

// cookie file format: https://everything.curl.dev/http/cookies/fileformat
func loadCookieJar(path string) (http.CookieJar, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer func() { _ = file.Close() }()

	jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
	if err != nil {
		return nil, err
	}

	sc := bufio.NewScanner(file)

	for sc.Scan() {
		line, httpOnly := strings.CutPrefix(strings.TrimSpace(sc.Text()), "#HttpOnly_")

		if strings.HasPrefix(line, "#") || line == "" {
			continue
		}

		parts := strings.Fields(line)
		if len(parts) != 6 && len(parts) != 7 {
			return nil, fmt.Errorf("got %d fields in line '%s', want 6 or 7", len(parts), line)
		}

		for i, v := range parts {
			parts[i] = strings.TrimSpace(v)
		}

		cookie := &http.Cookie{
			Domain:   parts[0],
			Path:     parts[2],
			Name:     parts[5],
			HttpOnly: httpOnly,
		}
		cookie.Secure, err = strconv.ParseBool(parts[3])
		if err != nil {
			return nil, err
		}
		expires, err := strconv.ParseInt(parts[4], 10, 64)
		if err != nil {
			return nil, err
		}
		if expires > 0 {
			cookie.Expires = time.Unix(expires, 0)
		}
		if len(parts) == 7 {
			cookie.Value = parts[6]
		}

		scheme := "http"
		if cookie.Secure {
			scheme = "https"
		}
		cookieURL := &url.URL{
			Scheme: scheme,
			Host:   cookie.Domain,
		}

		cookies := jar.Cookies(cookieURL)
		cookies = append(cookies, cookie)
		jar.SetCookies(cookieURL, cookies)
	}

	return jar, nil
}