firehol/netdata

View on GitHub
src/go/plugin/go.d/modules/httpcheck/cookiejar.go

Summary

Maintainability
A
2 hrs
Test Coverage
// 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
}