-
Notifications
You must be signed in to change notification settings - Fork 21
/
request.go
139 lines (116 loc) · 3.5 KB
/
request.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package rules
import (
"strings"
"github.com/AdguardTeam/urlfilter/filterutil"
"golang.org/x/net/publicsuffix"
)
// RequestType is the request types enumeration
type RequestType uint32
const (
// TypeDocument (main frame)
TypeDocument RequestType = 1 << iota
// TypeSubdocument (iframe) $subdocument
TypeSubdocument
// TypeScript (javascript, etc) $script
TypeScript
// TypeStylesheet (css) $stylesheet
TypeStylesheet
// TypeObject (flash, etc) $object
TypeObject
// TypeImage (any image) $image
TypeImage
// TypeXmlhttprequest (ajax/fetch) $xmlhttprequest
TypeXmlhttprequest
// TypeMedia (video/music) $media
TypeMedia
// TypeFont (any custom font) $font
TypeFont
// TypeWebsocket (a websocket connection) $websocket
TypeWebsocket
// TypeOther - any other request type
TypeOther
)
// Count returns count of the enabled flags
func (t RequestType) Count() int {
if t == 0 {
return 0
}
flags := uint32(t)
count := 0
var i uint
for i = 0; i < 32; i++ {
mask := uint32(1 << i)
if (flags & mask) == mask {
count++
}
}
return count
}
// Request represents a web request with all it's necessary properties
type Request struct {
RequestType RequestType // request type
ThirdParty bool // true if request is third-party
// IsHostnameRequest means that the request is for a given Hostname,
// and not for a URL, and we don't really know what protocol it is.
// This can be true for DNS requests, or for HTTP CONNECT, or SNI matching.
IsHostnameRequest bool
URL string // Request URL
URLLowerCase string // Request URL in lower case
Hostname string // Request hostname
Domain string // Request domain (eTLD+1)
// DNSType is the type of the resource record (RR) of a DNS request.
// See package github.com/miekg/dns for all acceptable constants.
DNSType uint16
SourceURL string // Source URL
SourceHostname string // Source hostname
SourceDomain string // Source domain (eTLD+1)
SortedClientTags []string // Sorted list of client tags ($ctag)
ClientIP string // Client IP address
ClientName string // Client name
}
// NewRequest creates a new instance of "Request" and populates it's fields
func NewRequest(url, sourceURL string, requestType RequestType) *Request {
r := Request{
RequestType: requestType,
URL: url,
URLLowerCase: strings.ToLower(url),
Hostname: filterutil.ExtractHostname(url),
SourceURL: sourceURL,
SourceHostname: filterutil.ExtractHostname(sourceURL),
}
domain, err := publicsuffix.EffectiveTLDPlusOne(r.Hostname)
if err == nil && domain != "" {
r.Domain = domain
} else {
r.Domain = r.Hostname
}
sourceDomain, err := publicsuffix.EffectiveTLDPlusOne(r.SourceHostname)
if err == nil && sourceDomain != "" {
r.SourceDomain = sourceDomain
} else {
r.SourceDomain = r.SourceHostname
}
if r.SourceDomain != "" && r.SourceDomain != r.Domain {
r.ThirdParty = true
}
return &r
}
// NewRequestForHostname creates a new instance of "Request" for matching hostname.
// It uses "http://" as a protocol and TypeDocument as a request type.
func NewRequestForHostname(hostname string) *Request {
r := Request{
RequestType: TypeDocument,
URL: "http://" + hostname + "/",
URLLowerCase: "http://" + hostname + "/",
Hostname: hostname,
ThirdParty: false,
IsHostnameRequest: true,
}
domain, err := publicsuffix.EffectiveTLDPlusOne(r.Hostname)
if err == nil && domain != "" {
r.Domain = domain
} else {
r.Domain = r.Hostname
}
return &r
}