forked from BishopFox/jsluice
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathurl-match-jquery.go
131 lines (110 loc) · 2.92 KB
/
url-match-jquery.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
package jsluice
import (
"strings"
"golang.org/x/exp/slices"
)
func matchJQuery() URLMatcher {
return URLMatcher{"call_expression", func(n *Node) *URL {
callName := n.ChildByFieldName("function").Content()
if !slices.Contains(
[]string{
"$.get", "$.post", "$.ajax",
"jQuery.get", "jQuery.post", "jQuery.ajax",
},
callName,
) {
return nil
}
// The jQuery ajax calls have a few different call signatures
// that we need to account for:
// jQuery.post( url [, data ] [, success ] [, dataType ] )
// jQuery.get( url [, data ] [, success ] [, dataType ] )
// jQuery.ajax( url [, settings ] )
// jQuery.post( [settings] )
// jQuery.get( [settings] )
// jQuery.ajax( [settings] )
//
// So we end up with three scenarios to deal with:
// 1. The URL comes first, then a data object
// 2. The URL comes first, then a settings object
// 3. A settings object comes first.
arguments := n.ChildByFieldName("arguments")
if arguments == nil {
return nil
}
firstArg := arguments.NamedChild(0)
if firstArg == nil {
return nil
}
secondArg := arguments.NamedChild(1)
m := &URL{
Type: callName,
Source: n.Content(),
}
// Infer the method for .post and .get calls
if strings.HasSuffix(callName, ".post") {
m.Method = "POST"
} else if strings.HasSuffix(callName, ".get") {
m.Method = "GET"
}
var settingsNode *Node
if firstArg.IsStringy() {
// first argument is the URL
m.URL = firstArg.CollapsedString()
// If the first arg is a URL, the second arg is a
// settings object for $.ajax, or a data object for
// $.get and $.post
if strings.HasSuffix(callName, ".ajax") {
settingsNode = secondArg
} else {
params := secondArg.AsObject().GetKeys()
if m.Method == "GET" {
m.QueryParams = params
} else {
m.BodyParams = params
m.ContentType = "application/x-www-form-urlencoded; charset=UTF-8"
}
}
}
if firstArg.Type() == "object" {
// first argument is a settings object
settingsNode = firstArg
}
if settingsNode == nil {
// we didn't end up with a settings node,
// so we can't infer anything else
return m
}
settings := settingsNode.AsObject()
if m.URL == "" {
m.URL = settings.GetNode("url").CollapsedString()
}
headers := settings.GetObject("headers")
m.Headers = headers.AsMap()
if m.Method == "" {
// method can be specified as either `method`, or
// `type`, and defaults to GET
m.Method = settings.GetString(
"method",
settings.GetString("type", "GET"),
)
}
params := settings.GetObject("data").GetKeys()
if m.Method == "GET" {
m.QueryParams = params
} else {
m.BodyParams = params
}
if m.Method != "GET" {
ct := headers.GetStringI("content-type", "")
if ct == "" {
ct = settings.GetString(
"contentType",
"application/x-www-form-urlencoded; charset=UTF-8",
)
}
m.ContentType = ct
}
return m
}}
}