forked from Stuk/server-replay
-
Notifications
You must be signed in to change notification settings - Fork 2
/
heuristic.js
124 lines (109 loc) · 3.76 KB
/
heuristic.js
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
/*
* Copyright (c) 2015 Adobe Systems Incorporated. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var URL = require("url");
module.exports = function (entries, request, options) {
var topPoints = 0;
var topEntry = null;
var entry;
for (var i = 0; i < entries.length; i++) {
entry = entries[i];
if (!entry.request.parsedUrl) {
entry.request.parsedUrl = URL.parse(entry.request.url, true);
}
if (!entry.request.indexedHeaders) {
entry.request.indexedHeaders = indexHeaders(entry.request.headers);
}
var points = rate(entry.request, request, options);
if (points > topPoints) {
topPoints = points;
topEntry = entry;
}
}
return topEntry;
};
function rate(entryRequest, request, options) {
var points = 0;
var name;
// method, host and pathname must match
if (
entryRequest.method !== request.method ||
(request.parsedUrl.host !== null && entryRequest.parsedUrl.host !== request.parsedUrl.host) ||
entryRequest.parsedUrl.pathname !== request.parsedUrl.pathname
) {
return 0;
}
// One point for matching above requirements
points += 1;
// each query
var entryQuery = entryRequest.parsedUrl.query;
var requestQuery = request.parsedUrl.query;
if (entryQuery && requestQuery) {
for (name in requestQuery) {
if (entryQuery[name] === undefined) {
points -= 0.5;
} else {
points += stripProtocol(entryQuery[name]) === stripProtocol(requestQuery[name]) ? 1 : 0;
}
}
for (name in entryQuery) {
if (requestQuery[name] === undefined) {
points -= 0.5;
}
}
}
// each post attribute
if (options.config.features.ratePost && entryRequest.postData && entryRequest.postData.mimeType === "application/json" && request.postData) {
const entryBody = JSON.parse(entryRequest.postData.text)
const requestBody = request.postData
for (name in requestBody) {
if (entryBody[name] === undefined) {
points -= 0.5;
} else {
points += JSON.stringify(entryBody[name]) === JSON.stringify(requestBody[name]) ? 1 : 0;
}
}
for (name in entryBody) {
if (requestBody[name] === undefined) {
points -= 0.5;
}
}
}
// each header
var entryHeaders = entryRequest.indexedHeaders;
var requestHeaders = request.headers;
for (name in requestHeaders) {
if (entryHeaders[name]) {
points += stripProtocol(entryHeaders[name]) === stripProtocol(requestHeaders[name]) ? 1 : 0;
}
// TODO handle missing headers and adjust score appropriately
}
return points;
}
function stripProtocol(string) {
if (typeof string === "string") {
return string.replace(/^https?/, "");
} else {
return string;
}
}
function indexHeaders(entryHeaders) {
var headers = {};
entryHeaders.forEach(function (header) {
headers[header.name.toLowerCase()] = header.value;
// TODO handle multiple of the same named header
});
return headers;
}