alexa-cookie2 5.0.4 → 5.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/lib/proxy.js +10 -8
- package/package.json +1 -1
- package/test/proxy-random-port.test.js +147 -0
package/README.md
CHANGED
|
@@ -55,6 +55,9 @@ Partly based on [Amazon Alexa Remote Control](http://blog.loetzimmer.de/2017/10/
|
|
|
55
55
|
Thank you for that work.
|
|
56
56
|
|
|
57
57
|
## Changelog:
|
|
58
|
+
### 5.0.5 (2026-07-06)
|
|
59
|
+
* (@Apollon77) Fix Proxy URL when no static port is provided
|
|
60
|
+
|
|
58
61
|
### 5.0.4 (2026-07-05)
|
|
59
62
|
* (@fkhr79, @blabond) Fix Amazon login proxy auth flow
|
|
60
63
|
|
package/lib/proxy.js
CHANGED
|
@@ -72,7 +72,7 @@ function customStringify(v, func, intent) {
|
|
|
72
72
|
|
|
73
73
|
function initAmazonProxy(_options, callbackCookie, callbackListening) {
|
|
74
74
|
const initialCookies = {};
|
|
75
|
-
const proxyBase = `http://${_options.proxyOwnIp}:${_options.proxyPort}/`;
|
|
75
|
+
const proxyBase = () => `http://${_options.proxyOwnIp}:${_options.proxyPort}/`;
|
|
76
76
|
const defaultAmazonHost = `www.${_options.baseAmazonPage}`;
|
|
77
77
|
const amazonProxyHosts = [];
|
|
78
78
|
|
|
@@ -106,7 +106,7 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
|
|
|
106
106
|
function amazonHostFromProxyUrl(url) {
|
|
107
107
|
if (!url) return null;
|
|
108
108
|
for (const host of amazonProxyHosts) {
|
|
109
|
-
if (url === `${proxyBase}${host}` || url.startsWith(`${proxyBase}${host}/`)) {
|
|
109
|
+
if (url === `${proxyBase()}${host}` || url.startsWith(`${proxyBase()}${host}/`)) {
|
|
110
110
|
return host;
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -286,22 +286,23 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
|
|
|
286
286
|
data = data.replace(///g, '/');
|
|
287
287
|
for (const host of amazonProxyHosts) {
|
|
288
288
|
const hostRegex = new RegExp(`https?://${escapeRegex(host)}:?[0-9]*/`, 'g');
|
|
289
|
-
data = data.replace(hostRegex, `${proxyBase}${host}/`);
|
|
289
|
+
data = data.replace(hostRegex, `${proxyBase()}${host}/`);
|
|
290
290
|
}
|
|
291
291
|
//_options.logger && _options.logger('REPLACEHOSTS: ' + dataOrig + ' --> ' + data);
|
|
292
292
|
return data;
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
function replaceHostsBack(data) {
|
|
296
|
+
const base = proxyBase();
|
|
296
297
|
for (const host of amazonProxyHosts) {
|
|
297
|
-
const hostRegex = new RegExp(`${escapeRegex(
|
|
298
|
+
const hostRegex = new RegExp(`${escapeRegex(base)}${escapeRegex(host)}/`, 'g');
|
|
298
299
|
data = data.replace(hostRegex, `https://${host}/`);
|
|
299
300
|
}
|
|
300
|
-
if (data ===
|
|
301
|
+
if (data === base) {
|
|
301
302
|
data = returnedInitUrl;
|
|
302
303
|
}
|
|
303
|
-
else if (data.startsWith(
|
|
304
|
-
data = `https://${defaultAmazonHost}/${data.slice(
|
|
304
|
+
else if (data.startsWith(base)) {
|
|
305
|
+
data = `https://${defaultAmazonHost}/${data.slice(base.length)}`;
|
|
305
306
|
}
|
|
306
307
|
return data;
|
|
307
308
|
}
|
|
@@ -466,7 +467,8 @@ function initAmazonProxy(_options, callbackCookie, callbackListening) {
|
|
|
466
467
|
_options.proxyPort = undefined;
|
|
467
468
|
}
|
|
468
469
|
const server = app.listen(_options.proxyPort, _options.proxyListenBind, function() {
|
|
469
|
-
_options.
|
|
470
|
+
_options.proxyPort = this.address().port;
|
|
471
|
+
_options.logger && _options.logger(`Alexa-Cookie: Proxy-Server listening on port ${_options.proxyPort}`);
|
|
470
472
|
callbackListening && callbackListening(server);
|
|
471
473
|
callbackListening = null;
|
|
472
474
|
}).on('error', err => {
|
package/package.json
CHANGED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const vm = require('vm');
|
|
6
|
+
|
|
7
|
+
const testName = 'proxy-random-port';
|
|
8
|
+
const outputDir = process.env.ALEXA_COOKIE_TEST_OUTPUT_DIR || path.join(__dirname, '..', 'test-output');
|
|
9
|
+
const outputFile = path.join(outputDir, `${testName}.txt`);
|
|
10
|
+
const lines = [];
|
|
11
|
+
|
|
12
|
+
function line(value = '') {
|
|
13
|
+
lines.push(value);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function writeOutput() {
|
|
17
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
18
|
+
fs.writeFileSync(outputFile, `${lines.join('\n')}\n`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function recordAssertion(description, fn) {
|
|
22
|
+
try {
|
|
23
|
+
fn();
|
|
24
|
+
line(`${description}: PASS`);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
line(`${description}: FAIL`);
|
|
27
|
+
writeOutput();
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const proxyFile = path.join(__dirname, '..', 'lib', 'proxy.js');
|
|
33
|
+
const source = fs.readFileSync(proxyFile, 'utf8');
|
|
34
|
+
|
|
35
|
+
const ASSIGNED_PORT = 3456;
|
|
36
|
+
let capturedProxyOptions;
|
|
37
|
+
|
|
38
|
+
function createExpressStub() {
|
|
39
|
+
return {
|
|
40
|
+
use() {},
|
|
41
|
+
get() {},
|
|
42
|
+
listen(port, bind, callback) {
|
|
43
|
+
const server = {
|
|
44
|
+
address: () => ({ port: ASSIGNED_PORT }),
|
|
45
|
+
on: () => server
|
|
46
|
+
};
|
|
47
|
+
callback && callback.call(server);
|
|
48
|
+
return server;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function loadProxyModule() {
|
|
54
|
+
capturedProxyOptions = undefined;
|
|
55
|
+
const module = { exports: {} };
|
|
56
|
+
const sandbox = {
|
|
57
|
+
Buffer,
|
|
58
|
+
URL,
|
|
59
|
+
__dirname: path.dirname(proxyFile),
|
|
60
|
+
console,
|
|
61
|
+
module,
|
|
62
|
+
exports: module.exports,
|
|
63
|
+
require(name) {
|
|
64
|
+
if (name === 'express') return createExpressStub;
|
|
65
|
+
if (name === 'http-proxy-response-rewrite') return () => {};
|
|
66
|
+
if (name === 'http-proxy-middleware') {
|
|
67
|
+
return {
|
|
68
|
+
createProxyMiddleware(_context, options) {
|
|
69
|
+
capturedProxyOptions = options;
|
|
70
|
+
return function proxyMiddleware() {};
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (name === 'cookie') {
|
|
75
|
+
return { parse: () => ({}) };
|
|
76
|
+
}
|
|
77
|
+
return require(name);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
vm.runInNewContext(source, sandbox, { filename: proxyFile });
|
|
81
|
+
return module.exports;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const proxyModule = loadProxyModule();
|
|
85
|
+
const formerDataStorePath = path.join(os.tmpdir(), `alexa-cookie-proxy-random-port-test-${Date.now()}.json`);
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const input = {
|
|
89
|
+
proxyOwnIp: '127.0.0.1',
|
|
90
|
+
proxyPort: 0,
|
|
91
|
+
proxyListenBind: '0.0.0.0',
|
|
92
|
+
baseAmazonPage: 'amazon.de',
|
|
93
|
+
baseAmazonPageHandle: '_de',
|
|
94
|
+
amazonPageProxyLanguage: 'de_DE',
|
|
95
|
+
acceptLanguage: 'de-DE',
|
|
96
|
+
proxyLogLevel: 'silent',
|
|
97
|
+
formerDataStorePath
|
|
98
|
+
};
|
|
99
|
+
proxyModule.initAmazonProxy(input);
|
|
100
|
+
|
|
101
|
+
const refererReq = {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
url: '/ap/cvf/verify',
|
|
104
|
+
headers: {
|
|
105
|
+
host: `127.0.0.1:${ASSIGNED_PORT}`,
|
|
106
|
+
referer: `http://127.0.0.1:${ASSIGNED_PORT}/www.amazon.com/ap/signin`
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const refererTarget = capturedProxyOptions.router(refererReq);
|
|
111
|
+
|
|
112
|
+
line('TEST: proxy random port (proxyPort 0)');
|
|
113
|
+
line('');
|
|
114
|
+
line('CODE UNDER TEST:');
|
|
115
|
+
line('- lib/proxy.js: proxyBase() lazy resolution');
|
|
116
|
+
line('- lib/proxy.js: listen callback writes assigned port to _options.proxyPort');
|
|
117
|
+
line('- lib/proxy.js: router()/amazonHostFromProxyUrl()');
|
|
118
|
+
line('');
|
|
119
|
+
line('INPUT:');
|
|
120
|
+
line(`proxyPort: ${input.proxyPort}`);
|
|
121
|
+
line(`assigned listen port: ${ASSIGNED_PORT}`);
|
|
122
|
+
line(`referer header: ${refererReq.headers.referer}`);
|
|
123
|
+
line('');
|
|
124
|
+
line('OBSERVED:');
|
|
125
|
+
line(`_options.proxyPort after init: ${input.proxyPort}`);
|
|
126
|
+
line(`referer router target: ${refererTarget}`);
|
|
127
|
+
line('');
|
|
128
|
+
line('ASSERTIONS:');
|
|
129
|
+
recordAssertion(`_options.proxyPort updated to ${ASSIGNED_PORT}`, () => {
|
|
130
|
+
assert.strictEqual(input.proxyPort, ASSIGNED_PORT);
|
|
131
|
+
});
|
|
132
|
+
recordAssertion('referer router target === "https://www.amazon.com"', () => {
|
|
133
|
+
assert.strictEqual(refererTarget, 'https://www.amazon.com');
|
|
134
|
+
});
|
|
135
|
+
line('');
|
|
136
|
+
line('RESULT: PASS');
|
|
137
|
+
writeOutput();
|
|
138
|
+
} catch (err) {
|
|
139
|
+
if (!lines.includes('RESULT: PASS')) {
|
|
140
|
+
line('');
|
|
141
|
+
line('RESULT: FAIL');
|
|
142
|
+
writeOutput();
|
|
143
|
+
}
|
|
144
|
+
throw err;
|
|
145
|
+
} finally {
|
|
146
|
+
fs.rmSync(formerDataStorePath, { force: true });
|
|
147
|
+
}
|