Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81141 views
1
'use strict'
2
3
var fs = require('fs')
4
var qs = require('querystring')
5
var validate = require('har-validator')
6
var util = require('util')
7
8
function Har (request) {
9
this.request = request
10
}
11
12
Har.prototype.reducer = function (obj, pair) {
13
// new property ?
14
if (obj[pair.name] === undefined) {
15
obj[pair.name] = pair.value
16
return obj
17
}
18
19
// existing? convert to array
20
var arr = [
21
obj[pair.name],
22
pair.value
23
]
24
25
obj[pair.name] = arr
26
27
return obj
28
}
29
30
Har.prototype.prep = function (data) {
31
// construct utility properties
32
data.queryObj = {}
33
data.headersObj = {}
34
data.postData.jsonObj = false
35
data.postData.paramsObj = false
36
37
// construct query objects
38
if (data.queryString && data.queryString.length) {
39
data.queryObj = data.queryString.reduce(this.reducer, {})
40
}
41
42
// construct headers objects
43
if (data.headers && data.headers.length) {
44
// loweCase header keys
45
data.headersObj = data.headers.reduceRight(function (headers, header) {
46
headers[header.name] = header.value
47
return headers
48
}, {})
49
}
50
51
// construct Cookie header
52
if (data.cookies && data.cookies.length) {
53
var cookies = data.cookies.map(function (cookie) {
54
return cookie.name + '=' + cookie.value
55
})
56
57
if (cookies.length) {
58
data.headersObj.cookie = cookies.join('; ')
59
}
60
}
61
62
// prep body
63
switch (data.postData.mimeType) {
64
case 'multipart/mixed':
65
case 'multipart/related':
66
case 'multipart/form-data':
67
case 'multipart/alternative':
68
// reset values
69
data.postData.mimeType = 'multipart/form-data'
70
break
71
72
case 'application/x-www-form-urlencoded':
73
if (!data.postData.params) {
74
data.postData.text = ''
75
} else {
76
data.postData.paramsObj = data.postData.params.reduce(this.reducer, {})
77
78
// always overwrite
79
data.postData.text = qs.stringify(data.postData.paramsObj)
80
}
81
break
82
83
case 'text/json':
84
case 'text/x-json':
85
case 'application/json':
86
case 'application/x-json':
87
data.postData.mimeType = 'application/json'
88
89
if (data.postData.text) {
90
try {
91
data.postData.jsonObj = JSON.parse(data.postData.text)
92
} catch (e) {
93
this.request.debug(e)
94
95
// force back to text/plain
96
data.postData.mimeType = 'text/plain'
97
}
98
}
99
break
100
}
101
102
return data
103
}
104
105
Har.prototype.options = function (options) {
106
// skip if no har property defined
107
if (!options.har) {
108
return options
109
}
110
111
var har = util._extend({}, options.har)
112
113
// only process the first entry
114
if (har.log && har.log.entries) {
115
har = har.log.entries[0]
116
}
117
118
// add optional properties to make validation successful
119
har.url = har.url || options.url || options.uri || options.baseUrl || '/'
120
har.httpVersion = har.httpVersion || 'HTTP/1.1'
121
har.queryString = har.queryString || []
122
har.headers = har.headers || []
123
har.cookies = har.cookies || []
124
har.postData = har.postData || {}
125
har.postData.mimeType = har.postData.mimeType || 'application/octet-stream'
126
127
har.bodySize = 0
128
har.headersSize = 0
129
har.postData.size = 0
130
131
if (!validate.request(har)) {
132
return options
133
}
134
135
// clean up and get some utility properties
136
var req = this.prep(har)
137
138
// construct new options
139
if (req.url) {
140
options.url = req.url
141
}
142
143
if (req.method) {
144
options.method = req.method
145
}
146
147
if (Object.keys(req.queryObj).length) {
148
options.qs = req.queryObj
149
}
150
151
if (Object.keys(req.headersObj).length) {
152
options.headers = req.headersObj
153
}
154
155
switch (req.postData.mimeType) {
156
case 'application/x-www-form-urlencoded':
157
options.form = req.postData.paramsObj
158
break
159
160
case 'application/json':
161
if (req.postData.jsonObj) {
162
options.body = req.postData.jsonObj
163
options.json = true
164
}
165
break
166
167
case 'multipart/form-data':
168
options.formData = {}
169
170
req.postData.params.forEach(function (param) {
171
var attachment = {}
172
173
if (!param.fileName && !param.fileName && !param.contentType) {
174
options.formData[param.name] = param.value
175
return
176
}
177
178
// attempt to read from disk!
179
if (param.fileName && !param.value) {
180
attachment.value = fs.createReadStream(param.fileName)
181
} else if (param.value) {
182
attachment.value = param.value
183
}
184
185
if (param.fileName) {
186
attachment.options = {
187
filename: param.fileName,
188
contentType: param.contentType ? param.contentType : null
189
}
190
}
191
192
options.formData[param.name] = attachment
193
})
194
break
195
196
default:
197
if (req.postData.text) {
198
options.body = req.postData.text
199
}
200
}
201
202
return options
203
}
204
205
exports.Har = Har
206
207