-
Notifications
You must be signed in to change notification settings - Fork 43
/
export.go
114 lines (103 loc) · 2.18 KB
/
export.go
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package kooky
import (
"context"
"fmt"
"io"
"net/http"
"strings"
)
const (
httpOnlyPrefix = `#HttpOnly_`
netscapeHeader = "# HTTP Cookie File\n\n"
)
// ExportCookies() export "cookies" in the Netscape format.
//
// curl, wget, ... use this format.
func ExportCookies[S CookieSeq | []*Cookie | []*http.Cookie](ctx context.Context, w io.Writer, cookies S) {
switch cookiesTyped := any(cookies).(type) {
case CookieSeq:
exportCookieSeq(ctx, w, cookiesTyped)
case []*Cookie:
exportCookieSlice(ctx, w, cookiesTyped)
case []*http.Cookie:
exportCookieSlice(ctx, w, cookiesTyped)
}
}
func exportCookie(w io.Writer, cookie *http.Cookie) {
var domain string
if cookie.HttpOnly {
domain = httpOnlyPrefix
}
domain += cookie.Domain
fmt.Fprintf(
w,
"%s\t%s\t%s\t%s\t%d\t%s\t%s\n",
domain,
netscapeBool(strings.HasPrefix(cookie.Domain, `.`)),
cookie.Path,
netscapeBool(cookie.Secure),
cookie.Expires.Unix(),
cookie.Name,
cookie.Value,
)
}
func exportCookieSlice[S []*T, T Cookie | http.Cookie](ctx context.Context, w io.Writer, cookies S) {
if len(cookies) < 1 {
return
}
var j int
for i, cookie := range cookies {
select {
case <-ctx.Done():
return
default:
}
if cookie == nil {
continue
}
fmt.Fprint(w, netscapeHeader)
j = i
break
}
// https://github.com/golang/go/issues/45380#issuecomment-1014950980
switch cookiesTyp := any(cookies).(type) {
case CookieSeq:
case []*http.Cookie:
for i := j; i < len(cookiesTyp); i++ {
if cookiesTyp[i] == nil {
continue
}
exportCookie(w, cookiesTyp[i])
}
case []*Cookie:
for i := j; i < len(cookiesTyp); i++ {
if cookiesTyp[i] == nil {
continue
}
exportCookie(w, &cookiesTyp[i].Cookie)
}
}
}
func exportCookieSeq(ctx context.Context, w io.Writer, seq CookieSeq) {
var init bool
for cookie, _ := range seq.OnlyCookies() {
select {
case <-ctx.Done():
return
default:
}
if !init {
fmt.Fprint(w, netscapeHeader)
init = true
}
exportCookie(w, &cookie.Cookie)
}
}
func (s CookieSeq) Export(ctx context.Context, w io.Writer) { exportCookieSeq(ctx, w, s) }
type netscapeBool bool
func (b netscapeBool) String() string {
if b {
return `TRUE`
}
return `FALSE`
}