master
go 89 lines 1.83 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package httpcheck
4
5 import (
6 "bufio"
7 "fmt"
8 "net/http"
9 "net/http/cookiejar"
10 "net/url"
11 "os"
12 "strconv"
13 "strings"
14 "time"
15
16 "golang.org/x/net/publicsuffix"
17 )
18
19 // TODO: implement proper cookie auth support
20 // relevant forum topic: https://community.netdata.cloud/t/howto-http-endpoint-collector-with-cookie-and-user-pass/3981/5?u=ilyam8
21
22 // cookie file format: https://everything.curl.dev/http/cookies/fileformat
23 func loadCookieJar(path string) (http.CookieJar, error) {
24 file, err := os.Open(path)
25 if err != nil {
26 return nil, err
27 }
28 defer func() { _ = file.Close() }()
29
30 jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
31 if err != nil {
32 return nil, err
33 }
34
35 sc := bufio.NewScanner(file)
36
37 for sc.Scan() {
38 line, httpOnly := strings.CutPrefix(strings.TrimSpace(sc.Text()), "#HttpOnly_")
39
40 if strings.HasPrefix(line, "#") || line == "" {
41 continue
42 }
43
44 parts := strings.Fields(line)
45 if len(parts) != 6 && len(parts) != 7 {
46 return nil, fmt.Errorf("got %d fields in line '%s', want 6 or 7", len(parts), line)
47 }
48
49 for i, v := range parts {
50 parts[i] = strings.TrimSpace(v)
51 }
52
53 cookie := &http.Cookie{
54 Domain: parts[0],
55 Path: parts[2],
56 Name: parts[5],
57 HttpOnly: httpOnly,
58 }
59 cookie.Secure, err = strconv.ParseBool(parts[3])
60 if err != nil {
61 return nil, err
62 }
63 expires, err := strconv.ParseInt(parts[4], 10, 64)
64 if err != nil {
65 return nil, err
66 }
67 if expires > 0 {
68 cookie.Expires = time.Unix(expires, 0)
69 }
70 if len(parts) == 7 {
71 cookie.Value = parts[6]
72 }
73
74 scheme := "http"
75 if cookie.Secure {
76 scheme = "https"
77 }
78 cookieURL := &url.URL{
79 Scheme: scheme,
80 Host: cookie.Domain,
81 }
82
83 cookies := jar.Cookies(cookieURL)
84 cookies = append(cookies, cookie)
85 jar.SetCookies(cookieURL, cookies)
86 }
87
88 return jar, nil
89 }