github.com/netdata/go.d.plugin@v0.58.1/modules/httpcheck/cookiejar.go (about)

     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  }