@decodo/mcp-server 1.2.5 → 1.3.0

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.
Files changed (58) hide show
  1. package/README.md +61 -43
  2. package/build/auth/credential.js +4 -1
  3. package/build/auth/credential.js.map +1 -1
  4. package/build/clients/hosts.js +10 -0
  5. package/build/clients/hosts.js.map +1 -0
  6. package/build/clients/scraper-api-client.js +15 -5
  7. package/build/clients/scraper-api-client.js.map +1 -1
  8. package/build/index.js +2 -2
  9. package/build/index.js.map +1 -1
  10. package/build/oauth/backend.js +3 -0
  11. package/build/oauth/backend.js.map +1 -0
  12. package/build/oauth/backends/decodo/index.js +71 -0
  13. package/build/oauth/backends/decodo/index.js.map +1 -0
  14. package/build/oauth/backends/decodo/request-jwt.js +62 -0
  15. package/build/oauth/backends/decodo/request-jwt.js.map +1 -0
  16. package/build/oauth/backends/decodo/token-exchange.js +88 -0
  17. package/build/oauth/backends/decodo/token-exchange.js.map +1 -0
  18. package/build/oauth/backends/mock/dashboard.js +84 -0
  19. package/build/oauth/backends/mock/dashboard.js.map +1 -0
  20. package/build/oauth/backends/mock/index.js +42 -0
  21. package/build/oauth/backends/mock/index.js.map +1 -0
  22. package/build/oauth/backends/mock/subscription-api.js +130 -0
  23. package/build/oauth/backends/mock/subscription-api.js.map +1 -0
  24. package/build/oauth/bounded-body.js +29 -0
  25. package/build/oauth/bounded-body.js.map +1 -0
  26. package/build/oauth/clients-store.js +142 -0
  27. package/build/oauth/clients-store.js.map +1 -0
  28. package/build/oauth/config.js +77 -0
  29. package/build/oauth/config.js.map +1 -0
  30. package/build/oauth/cookies.js +25 -0
  31. package/build/oauth/cookies.js.map +1 -0
  32. package/build/oauth/index.js +46 -0
  33. package/build/oauth/index.js.map +1 -0
  34. package/build/oauth/provider.js +172 -0
  35. package/build/oauth/provider.js.map +1 -0
  36. package/build/oauth/redirect-uris.js +17 -0
  37. package/build/oauth/redirect-uris.js.map +1 -0
  38. package/build/oauth/router.js +68 -0
  39. package/build/oauth/router.js.map +1 -0
  40. package/build/oauth/sealer.js +55 -0
  41. package/build/oauth/sealer.js.map +1 -0
  42. package/build/oauth/token-exchange.js +17 -0
  43. package/build/oauth/token-exchange.js.map +1 -0
  44. package/build/oauth/ttl-store.js +47 -0
  45. package/build/oauth/ttl-store.js.map +1 -0
  46. package/build/server/app.js +77 -0
  47. package/build/server/app.js.map +1 -0
  48. package/build/server/revoked-credentials.js +25 -0
  49. package/build/server/revoked-credentials.js.map +1 -0
  50. package/build/server/sapi-base-server.js +2 -2
  51. package/build/server/sapi-base-server.js.map +1 -1
  52. package/build/server/sapi-http-server.js +2 -2
  53. package/build/server/sapi-http-server.js.map +1 -1
  54. package/build/server/trust-proxy.js +19 -0
  55. package/build/server/trust-proxy.js.map +1 -0
  56. package/build/server.js +6 -44
  57. package/build/server.js.map +1 -1
  58. package/package.json +3 -9
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DecodoOAuthProvider = exports.UnknownAuthorizationRequestError = exports.callbackQueryFrom = exports.MAX_PENDING_COOKIE_LENGTH = exports.MAX_CODE_CHALLENGE_LENGTH = exports.MAX_STATE_LENGTH = exports.PENDING_COOKIE = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const errors_js_1 = require("@modelcontextprotocol/sdk/server/auth/errors.js");
6
+ const logger_1 = require("../logger");
7
+ const clients_store_1 = require("./clients-store");
8
+ const token_exchange_1 = require("./token-exchange");
9
+ exports.PENDING_COOKIE = 'decodo_oauth_pending';
10
+ const PENDING_TTL_MS = 10 * 60 * 1000;
11
+ const CODE_TTL_MS = 60 * 1000;
12
+ exports.MAX_STATE_LENGTH = 1024;
13
+ exports.MAX_CODE_CHALLENGE_LENGTH = 128;
14
+ exports.MAX_PENDING_COOKIE_LENGTH = 3072;
15
+ const MAX_CALLBACK_PARAM_LENGTH = { code: 512, state: 256, error: 64, error_description: 512 };
16
+ const SEAL = {
17
+ PENDING: 'pending',
18
+ CODE: 'code',
19
+ };
20
+ const callbackQueryFrom = (query) => {
21
+ const picked = {};
22
+ for (const [key, max] of Object.entries(MAX_CALLBACK_PARAM_LENGTH)) {
23
+ const value = query[key];
24
+ if (typeof value === 'string' && value.length > 0) {
25
+ picked[key] = value.slice(0, max);
26
+ }
27
+ }
28
+ return picked;
29
+ };
30
+ exports.callbackQueryFrom = callbackQueryFrom;
31
+ class UnknownAuthorizationRequestError extends Error {
32
+ constructor() {
33
+ super('This sign-in request is unknown or has expired. Start again from your MCP client.');
34
+ this.name = 'UnknownAuthorizationRequestError';
35
+ }
36
+ }
37
+ exports.UnknownAuthorizationRequestError = UnknownAuthorizationRequestError;
38
+ const EXCHANGE_ERROR_TO_OAUTH_ERROR = {
39
+ [token_exchange_1.TOKEN_EXCHANGE_ERROR.INVALID_GRANT]: errors_js_1.InvalidGrantError,
40
+ [token_exchange_1.TOKEN_EXCHANGE_ERROR.INVALID_CLIENT]: errors_js_1.ServerError,
41
+ [token_exchange_1.TOKEN_EXCHANGE_ERROR.SERVER_ERROR]: errors_js_1.ServerError,
42
+ };
43
+ const randomToken = () => (0, node_crypto_1.randomBytes)(32).toString('base64url');
44
+ const pkceChallenge = (verifier) => (0, node_crypto_1.createHash)('sha256').update(verifier).digest('base64url');
45
+ class DecodoOAuthProvider {
46
+ constructor({ clientsStore, backend, sealer, callbackUrl, onTokenIssued, }) {
47
+ this.clientsStore = clientsStore;
48
+ this.backend = backend;
49
+ this.sealer = sealer;
50
+ this.onTokenIssued = onTokenIssued;
51
+ this.cookieOptions = {
52
+ httpOnly: true,
53
+ secure: callbackUrl.protocol === 'https:',
54
+ sameSite: 'lax',
55
+ path: callbackUrl.pathname,
56
+ maxAge: PENDING_TTL_MS,
57
+ };
58
+ }
59
+ async authorize(client, params, res) {
60
+ var _a, _b;
61
+ if (params.state && params.state.length > exports.MAX_STATE_LENGTH) {
62
+ throw new errors_js_1.InvalidRequestError(`state must be at most ${exports.MAX_STATE_LENGTH} characters`);
63
+ }
64
+ if (params.codeChallenge.length > exports.MAX_CODE_CHALLENGE_LENGTH) {
65
+ throw new errors_js_1.InvalidRequestError(`code_challenge must be at most ${exports.MAX_CODE_CHALLENGE_LENGTH} characters`);
66
+ }
67
+ if (((_a = params.scopes) !== null && _a !== void 0 ? _a : []).join(' ').length > clients_store_1.MAX_SCOPE_LENGTH) {
68
+ throw new errors_js_1.InvalidRequestError(`scope must be at most ${clients_store_1.MAX_SCOPE_LENGTH} characters`);
69
+ }
70
+ const pending = {
71
+ requestId: randomToken(),
72
+ state: randomToken(),
73
+ codeVerifier: randomToken(),
74
+ clientId: client.client_id,
75
+ redirectUri: params.redirectUri,
76
+ codeChallenge: params.codeChallenge,
77
+ scopes: (_b = params.scopes) !== null && _b !== void 0 ? _b : [],
78
+ clientState: params.state,
79
+ };
80
+ const cookie = this.sealer.seal(SEAL.PENDING, pending, PENDING_TTL_MS);
81
+ if (cookie.length > exports.MAX_PENDING_COOKIE_LENGTH) {
82
+ throw new errors_js_1.InvalidRequestError('authorization request is too large');
83
+ }
84
+ const url = await this.backend.authorizationUrl({
85
+ state: pending.state,
86
+ codeChallenge: pkceChallenge(pending.codeVerifier),
87
+ });
88
+ (0, logger_1.log)('info', 'oauth.authorize', { clientId: client.client_id, requestId: pending.requestId });
89
+ res.cookie(exports.PENDING_COOKIE, cookie, this.cookieOptions);
90
+ res.redirect(302, url.href);
91
+ }
92
+ handleCallback({ query, pendingCookie, res }) {
93
+ const pending = pendingCookie ? this.sealer.unseal(SEAL.PENDING, pendingCookie) : undefined;
94
+ if (!pending || !query.state || query.state !== pending.state) {
95
+ throw new UnknownAuthorizationRequestError();
96
+ }
97
+ res.clearCookie(exports.PENDING_COOKIE, this.cookieOptions);
98
+ const redirect = new URL(pending.redirectUri);
99
+ if (pending.clientState) {
100
+ redirect.searchParams.set('state', pending.clientState);
101
+ }
102
+ if (query.error || !query.code) {
103
+ const error = query.error || errors_js_1.InvalidRequestError.errorCode;
104
+ redirect.searchParams.set('error', error);
105
+ if (query.error_description) {
106
+ redirect.searchParams.set('error_description', query.error_description);
107
+ }
108
+ (0, logger_1.log)('info', 'oauth.callback.denied', { requestId: pending.requestId, error });
109
+ return redirect.href;
110
+ }
111
+ const issued = {
112
+ requestId: pending.requestId,
113
+ clientId: pending.clientId,
114
+ redirectUri: pending.redirectUri,
115
+ codeChallenge: pending.codeChallenge,
116
+ scopes: pending.scopes,
117
+ codeVerifier: pending.codeVerifier,
118
+ upstreamCode: query.code,
119
+ };
120
+ redirect.searchParams.set('code', this.sealer.seal(SEAL.CODE, issued, CODE_TTL_MS));
121
+ (0, logger_1.log)('info', 'oauth.callback.approved', { requestId: pending.requestId });
122
+ return redirect.href;
123
+ }
124
+ async challengeForAuthorizationCode(client, authorizationCode) {
125
+ return this.issuedCode(client, authorizationCode).codeChallenge;
126
+ }
127
+ async exchangeAuthorizationCode(client, authorizationCode, _codeVerifier, redirectUri) {
128
+ var _a;
129
+ const issued = this.issuedCode(client, authorizationCode);
130
+ if (redirectUri && redirectUri !== issued.redirectUri) {
131
+ throw new errors_js_1.InvalidGrantError('redirect_uri does not match the authorization request');
132
+ }
133
+ const scraperApiKey = await this.redeem(issued);
134
+ (0, logger_1.log)('info', 'oauth.token.issued', { requestId: issued.requestId, clientId: client.client_id });
135
+ (_a = this.onTokenIssued) === null || _a === void 0 ? void 0 : _a.call(this, scraperApiKey);
136
+ return {
137
+ access_token: scraperApiKey,
138
+ token_type: 'bearer',
139
+ scope: issued.scopes.length > 0 ? issued.scopes.join(' ') : undefined,
140
+ };
141
+ }
142
+ async exchangeRefreshToken() {
143
+ throw new errors_js_1.UnsupportedGrantTypeError('refresh tokens are not issued; reconnect to get a new key');
144
+ }
145
+ async verifyAccessToken(token) {
146
+ if (!token.trim()) {
147
+ throw new errors_js_1.InvalidTokenError('empty access token');
148
+ }
149
+ return { token, clientId: 'unknown', scopes: [] };
150
+ }
151
+ issuedCode(client, authorizationCode) {
152
+ const issued = this.sealer.unseal(SEAL.CODE, authorizationCode);
153
+ if (!issued || issued.clientId !== client.client_id) {
154
+ throw new errors_js_1.InvalidGrantError('unknown or expired authorization code');
155
+ }
156
+ return issued;
157
+ }
158
+ async redeem(issued) {
159
+ try {
160
+ return await this.backend.exchange({ code: issued.upstreamCode, codeVerifier: issued.codeVerifier });
161
+ }
162
+ catch (error) {
163
+ if (error instanceof token_exchange_1.TokenExchangeError) {
164
+ (0, logger_1.log)('warn', 'oauth.token_exchange.failed', { requestId: issued.requestId, code: error.code, error: error.message });
165
+ throw new EXCHANGE_ERROR_TO_OAUTH_ERROR[error.code](error.message);
166
+ }
167
+ throw error;
168
+ }
169
+ }
170
+ }
171
+ exports.DecodoOAuthProvider = DecodoOAuthProvider;
172
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/oauth/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.disallowedRedirectUris = exports.isAllowedRedirectUri = exports.isLoopbackRedirectUri = void 0;
4
+ const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
5
+ const isLoopbackRedirectUri = (uri) => {
6
+ if (!URL.canParse(uri)) {
7
+ return false;
8
+ }
9
+ const url = new URL(uri);
10
+ return url.protocol === 'http:' && LOOPBACK_HOSTS.has(url.hostname);
11
+ };
12
+ exports.isLoopbackRedirectUri = isLoopbackRedirectUri;
13
+ const isAllowedRedirectUri = (uri, allowed) => allowed.includes(uri) || (0, exports.isLoopbackRedirectUri)(uri);
14
+ exports.isAllowedRedirectUri = isAllowedRedirectUri;
15
+ const disallowedRedirectUris = (uris, allowed) => uris.filter(uri => !(0, exports.isAllowedRedirectUri)(uri, allowed));
16
+ exports.disallowedRedirectUris = disallowedRedirectUris;
17
+ //# sourceMappingURL=redirect-uris.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect-uris.js","sourceRoot":"","sources":["../../src/oauth/redirect-uris.ts"],"names":[],"mappings":";;;AAAA,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;AAE7D,MAAM,qBAAqB,GAAG,CAAC,GAAW,EAAW,EAAE;IAC5D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAEzB,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACtE,CAAC,CAAC;AARW,QAAA,qBAAqB,yBAQhC;AAEK,MAAM,oBAAoB,GAAG,CAAC,GAAW,EAAE,OAAiB,EAAW,EAAE,CAC9E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAA,6BAAqB,EAAC,GAAG,CAAC,CAAC;AADzC,QAAA,oBAAoB,wBACqB;AAE/C,MAAM,sBAAsB,GAAG,CAAC,IAAc,EAAE,OAAiB,EAAY,EAAE,CACpF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAA,4BAAoB,EAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AAD7C,QAAA,sBAAsB,0BACuB"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.oauthRouter = void 0;
7
+ const express_1 = __importDefault(require("express"));
8
+ const authorize_js_1 = require("@modelcontextprotocol/sdk/server/auth/handlers/authorize.js");
9
+ const register_js_1 = require("@modelcontextprotocol/sdk/server/auth/handlers/register.js");
10
+ const token_js_1 = require("@modelcontextprotocol/sdk/server/auth/handlers/token.js");
11
+ const router_js_1 = require("@modelcontextprotocol/sdk/server/auth/router.js");
12
+ const logger_1 = require("../logger");
13
+ const config_1 = require("./config");
14
+ const cookies_1 = require("./cookies");
15
+ const provider_1 = require("./provider");
16
+ const provider_2 = require("./provider");
17
+ const RESOURCE_NAME = 'Decodo MCP Server';
18
+ const DOCUMENTATION_URL = new URL('https://github.com/Decodo/mcp-server#readme');
19
+ const RATE_LIMIT_WINDOW_MS = 15 * 60 * 1000;
20
+ const RATE_LIMITS = {
21
+ register: { windowMs: RATE_LIMIT_WINDOW_MS, max: 500 },
22
+ token: { windowMs: RATE_LIMIT_WINDOW_MS, max: 2000 },
23
+ authorize: { windowMs: RATE_LIMIT_WINDOW_MS, max: 200 },
24
+ };
25
+ const errorPage = (message) => `<!doctype html>
26
+ <html lang="en"><head><meta charset="utf-8"><title>Decodo sign-in</title></head>
27
+ <body style="font-family: system-ui, sans-serif; max-width: 32rem; margin: 3rem auto; padding: 0 1rem;">
28
+ <h1>Sign-in could not be completed</h1>
29
+ <p>${message}</p>
30
+ </body></html>`;
31
+ const buildOAuthMetadata = ({ provider, issuerUrl, }) => (Object.assign(Object.assign({}, (0, router_js_1.createOAuthMetadata)({ provider, issuerUrl, serviceDocumentationUrl: DOCUMENTATION_URL })), { grant_types_supported: ['authorization_code'], token_endpoint_auth_methods_supported: ['none'], client_id_metadata_document_supported: true }));
32
+ const oauthRouter = ({ provider, issuerUrl, resourceServerUrl, }) => {
33
+ const metadata = buildOAuthMetadata({ provider, issuerUrl });
34
+ const router = express_1.default.Router();
35
+ router.use(new URL(metadata.authorization_endpoint).pathname, (0, authorize_js_1.authorizationHandler)({ provider, rateLimit: RATE_LIMITS.authorize }));
36
+ router.use(new URL(metadata.token_endpoint).pathname, (0, token_js_1.tokenHandler)({ provider, rateLimit: RATE_LIMITS.token }));
37
+ if (metadata.registration_endpoint) {
38
+ router.use(new URL(metadata.registration_endpoint).pathname, (0, register_js_1.clientRegistrationHandler)({ clientsStore: provider.clientsStore, rateLimit: RATE_LIMITS.register }));
39
+ }
40
+ router.use((0, router_js_1.mcpAuthMetadataRouter)({
41
+ oauthMetadata: metadata,
42
+ resourceServerUrl,
43
+ resourceName: RESOURCE_NAME,
44
+ serviceDocumentationUrl: DOCUMENTATION_URL,
45
+ }));
46
+ router.get(config_1.CALLBACK_PATH, (req, res) => {
47
+ res.setHeader('Cache-Control', 'no-store');
48
+ try {
49
+ const redirect = provider.handleCallback({
50
+ query: (0, provider_2.callbackQueryFrom)(req.query),
51
+ pendingCookie: (0, cookies_1.cookieValue)(req.headers.cookie, provider_1.PENDING_COOKIE),
52
+ res,
53
+ });
54
+ res.redirect(302, redirect);
55
+ }
56
+ catch (error) {
57
+ if (error instanceof provider_1.UnknownAuthorizationRequestError) {
58
+ res.status(400).send(errorPage(error.message));
59
+ return;
60
+ }
61
+ (0, logger_1.log)('error', 'oauth.callback.failed', { error: error instanceof Error ? error.message : String(error) });
62
+ res.status(500).send(errorPage('Something went wrong on our side. Try connecting again.'));
63
+ }
64
+ });
65
+ return router;
66
+ };
67
+ exports.oauthRouter = oauthRouter;
68
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/oauth/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Sealer = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const ALGORITHM = 'aes-256-gcm';
6
+ const IV_BYTES = 12;
7
+ const TAG_BYTES = 16;
8
+ class Sealer {
9
+ constructor(secret, now = Date.now) {
10
+ this.now = now;
11
+ this.key = (0, node_crypto_1.createHash)('sha256').update(secret).digest();
12
+ }
13
+ static randomSecret() {
14
+ return (0, node_crypto_1.randomBytes)(32).toString('base64url');
15
+ }
16
+ seal(purpose, payload, ttlMs) {
17
+ const iv = (0, node_crypto_1.randomBytes)(IV_BYTES);
18
+ const cipher = (0, node_crypto_1.createCipheriv)(ALGORITHM, this.key, iv);
19
+ cipher.setAAD(Buffer.from(purpose));
20
+ const body = ttlMs === undefined ? Object.assign({}, payload) : Object.assign(Object.assign({}, payload), { exp: this.now() + ttlMs });
21
+ const encrypted = Buffer.concat([cipher.update(JSON.stringify(body), 'utf8'), cipher.final()]);
22
+ return Buffer.concat([iv, encrypted, cipher.getAuthTag()]).toString('base64url');
23
+ }
24
+ unseal(purpose, token) {
25
+ let buffer;
26
+ try {
27
+ buffer = Buffer.from(token, 'base64url');
28
+ }
29
+ catch (_a) {
30
+ return;
31
+ }
32
+ if (buffer.length <= IV_BYTES + TAG_BYTES) {
33
+ return;
34
+ }
35
+ const iv = buffer.subarray(0, IV_BYTES);
36
+ const tag = buffer.subarray(buffer.length - TAG_BYTES);
37
+ const encrypted = buffer.subarray(IV_BYTES, buffer.length - TAG_BYTES);
38
+ try {
39
+ const decipher = (0, node_crypto_1.createDecipheriv)(ALGORITHM, this.key, iv);
40
+ decipher.setAAD(Buffer.from(purpose));
41
+ decipher.setAuthTag(tag);
42
+ const body = JSON.parse(Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8'));
43
+ if (body.exp !== undefined && body.exp <= this.now()) {
44
+ return;
45
+ }
46
+ delete body.exp;
47
+ return body;
48
+ }
49
+ catch (_b) {
50
+ return;
51
+ }
52
+ }
53
+ }
54
+ exports.Sealer = Sealer;
55
+ //# sourceMappingURL=sealer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sealer.js","sourceRoot":"","sources":["../../src/oauth/sealer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenExchangeError = exports.TOKEN_EXCHANGE_ERROR = void 0;
4
+ exports.TOKEN_EXCHANGE_ERROR = {
5
+ INVALID_GRANT: 'invalid_grant',
6
+ INVALID_CLIENT: 'invalid_client',
7
+ SERVER_ERROR: 'server_error',
8
+ };
9
+ class TokenExchangeError extends Error {
10
+ constructor(code, message) {
11
+ super(message);
12
+ this.code = code;
13
+ this.name = 'TokenExchangeError';
14
+ }
15
+ }
16
+ exports.TokenExchangeError = TokenExchangeError;
17
+ //# sourceMappingURL=token-exchange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-exchange.js","sourceRoot":"","sources":["../../src/oauth/token-exchange.ts"],"names":[],"mappings":";;;AAAa,QAAA,oBAAoB,GAAG;IAClC,aAAa,EAAE,eAAe;IAC9B,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,cAAc;CACpB,CAAC;AAIX,MAAa,kBAAmB,SAAQ,KAAK;IAC3C,YACW,IAA4B,EACrC,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHN,SAAI,GAAJ,IAAI,CAAwB;QAIrC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AARD,gDAQC"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TtlStore = void 0;
4
+ class TtlStore {
5
+ constructor(ttlMs, now = Date.now) {
6
+ this.ttlMs = ttlMs;
7
+ this.now = now;
8
+ this.entries = new Map();
9
+ }
10
+ set(key, value) {
11
+ this.sweep();
12
+ this.entries.set(key, { value, expiresAt: this.now() + this.ttlMs });
13
+ }
14
+ get(key) {
15
+ const entry = this.entries.get(key);
16
+ if (!entry) {
17
+ return;
18
+ }
19
+ if (entry.expiresAt <= this.now()) {
20
+ this.entries.delete(key);
21
+ return;
22
+ }
23
+ return entry.value;
24
+ }
25
+ take(key) {
26
+ const value = this.get(key);
27
+ this.entries.delete(key);
28
+ return value;
29
+ }
30
+ delete(key) {
31
+ this.entries.delete(key);
32
+ }
33
+ get size() {
34
+ this.sweep();
35
+ return this.entries.size;
36
+ }
37
+ sweep() {
38
+ const now = this.now();
39
+ for (const [key, entry] of this.entries) {
40
+ if (entry.expiresAt <= now) {
41
+ this.entries.delete(key);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ exports.TtlStore = TtlStore;
47
+ //# sourceMappingURL=ttl-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ttl-store.js","sourceRoot":"","sources":["../../src/oauth/ttl-store.ts"],"names":[],"mappings":";;;AAKA,MAAa,QAAQ;IAGnB,YACmB,KAAa,EACb,MAAoB,IAAI,CAAC,GAAG;QAD5B,UAAK,GAAL,KAAK,CAAQ;QACb,QAAG,GAAH,GAAG,CAAyB;QAJ9B,YAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAKpD,CAAC;IAEJ,GAAG,CAAC,GAAW,EAAE,KAAQ;QACvB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEpC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QAED,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,GAAW;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI,IAAI;QACN,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAEO,KAAK;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACxC,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;gBAC3B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;CACF;AApDD,4BAoDC"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createApp = void 0;
7
+ const cors_1 = __importDefault(require("cors"));
8
+ const express_1 = __importDefault(require("express"));
9
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
10
+ const auth_1 = require("../auth");
11
+ const oauth_1 = require("../oauth");
12
+ const utils_1 = require("../utils");
13
+ const cors_2 = require("./cors");
14
+ const revoked_credentials_1 = require("./revoked-credentials");
15
+ const sapi_http_server_1 = require("./sapi-http-server");
16
+ const wwwAuthenticate = (resourceMetadataUrl, error) => error
17
+ ? `Bearer error="${error}", resource_metadata="${resourceMetadataUrl}"`
18
+ : `Bearer resource_metadata="${resourceMetadataUrl}"`;
19
+ const createApp = ({ oauth: oauthConfig, trustProxy = false, revokedCredentials = new revoked_credentials_1.RevokedCredentials(), fetch, }) => {
20
+ const app = (0, express_1.default)();
21
+ const oauth = (0, oauth_1.createOAuth)(oauthConfig, {
22
+ fetch,
23
+ onTokenIssued: scraperApiKey => {
24
+ const credential = (0, auth_1.credentialFromValue)(scraperApiKey);
25
+ if (credential) {
26
+ revokedCredentials.remove(credential);
27
+ }
28
+ },
29
+ });
30
+ app.set('trust proxy', trustProxy);
31
+ app.use((0, cors_1.default)(cors_2.corsOptions));
32
+ app.use(express_1.default.json());
33
+ app.use(oauth.router);
34
+ app.get('/mcp', (_req, res) => {
35
+ res.status(200).send('server up, use POST /mcp to see available tools');
36
+ });
37
+ app.post('/mcp', async (req, res) => {
38
+ const auth = req.headers.authorization;
39
+ if (!auth) {
40
+ res.set('WWW-Authenticate', wwwAuthenticate(oauth.resourceMetadataUrl));
41
+ res.status(401).send('Unauthorized');
42
+ return;
43
+ }
44
+ const credential = (0, auth_1.credentialFromAuthHeader)(auth);
45
+ if (!credential) {
46
+ res.set('WWW-Authenticate', wwwAuthenticate(oauth.resourceMetadataUrl, 'invalid_token'));
47
+ res.status(401).send("Valid 'Basic' or 'Bearer' authorization required");
48
+ return;
49
+ }
50
+ if (revokedCredentials.has(credential)) {
51
+ res.set('WWW-Authenticate', wwwAuthenticate(oauth.resourceMetadataUrl, 'invalid_token'));
52
+ res.status(401).send('The Scraping API rejected this credential; sign in again');
53
+ return;
54
+ }
55
+ const toolsets = (0, utils_1.resolveToolsets)(req.query.toolsets);
56
+ const server = new sapi_http_server_1.ScraperAPIHttpServer({
57
+ toolsets,
58
+ auth: credential,
59
+ onAuthenticationError: rejected => revokedCredentials.add(rejected),
60
+ });
61
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
62
+ sessionIdGenerator: undefined,
63
+ enableJsonResponse: false,
64
+ });
65
+ res.on('close', () => {
66
+ transport.close();
67
+ });
68
+ await server.connect(transport);
69
+ await transport.handleRequest(req, res, req.body);
70
+ });
71
+ app.get('/healthz', (_req, res) => {
72
+ res.status(200).send('ok');
73
+ });
74
+ return app;
75
+ };
76
+ exports.createApp = createApp;
77
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,sDAA8B;AAC9B,0FAAmG;AACnG,kCAAwE;AACxE,oCAAuC;AAEvC,oCAA2C;AAC3C,iCAAqC;AACrC,+DAA2D;AAC3D,yDAA0D;AAK1D,MAAM,eAAe,GAAG,CAAC,mBAA2B,EAAE,KAAc,EAAU,EAAE,CAC9E,KAAK;IACH,CAAC,CAAC,iBAAiB,KAAK,yBAAyB,mBAAmB,GAAG;IACvE,CAAC,CAAC,6BAA6B,mBAAmB,GAAG,CAAC;AAEnD,MAAM,SAAS,GAAG,CAAC,EACxB,KAAK,EAAE,WAAW,EAClB,UAAU,GAAG,KAAK,EAClB,kBAAkB,GAAG,IAAI,wCAAkB,EAAE,EAC7C,KAAK,GAMN,EAAmB,EAAE;IACpB,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;IACtB,MAAM,KAAK,GAAG,IAAA,mBAAW,EAAC,WAAW,EAAE;QACrC,KAAK;QACL,aAAa,EAAE,aAAa,CAAC,EAAE;YAC7B,MAAM,UAAU,GAAG,IAAA,0BAAmB,EAAC,aAAa,CAAC,CAAC;YAEtD,IAAI,UAAU,EAAE,CAAC;gBACf,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;IAEnC,GAAG,CAAC,GAAG,CAAC,IAAA,cAAI,EAAC,kBAAW,CAAC,CAAC,CAAC;IAC3B,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExB,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAEtB,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAC5B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QAEvC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;YACxE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACrC,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,IAAA,+BAAwB,EAAC,IAAI,CAAC,CAAC;QAElD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,KAAK,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC,CAAC;YACzF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YACzE,OAAO;QACT,CAAC;QAED,IAAI,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YACvC,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,KAAK,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC,CAAC;YACzF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;YACjF,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAA,uBAAe,EAAC,GAAG,CAAC,KAAK,CAAC,QAAkB,CAAC,CAAC;QAE/D,MAAM,MAAM,GAAG,IAAI,uCAAoB,CAAC;YACtC,QAAQ;YACR,IAAI,EAAE,UAAU;YAChB,qBAAqB,EAAE,QAAQ,CAAC,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;SACpE,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,IAAI,iDAA6B,CAAC;YAClD,kBAAkB,EAAE,SAAS;YAC7B,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACnB,SAAS,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEhC,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAChC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AApFW,QAAA,SAAS,aAoFpB"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RevokedCredentials = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const ttl_store_1 = require("../oauth/ttl-store");
6
+ const REMEMBER_MS = 5 * 60 * 1000;
7
+ class RevokedCredentials {
8
+ constructor() {
9
+ this.rejected = new ttl_store_1.TtlStore(REMEMBER_MS);
10
+ }
11
+ add(credential) {
12
+ this.rejected.set(RevokedCredentials.fingerprint(credential), true);
13
+ }
14
+ has(credential) {
15
+ return this.rejected.get(RevokedCredentials.fingerprint(credential)) === true;
16
+ }
17
+ remove(credential) {
18
+ this.rejected.delete(RevokedCredentials.fingerprint(credential));
19
+ }
20
+ static fingerprint({ type, value }) {
21
+ return (0, node_crypto_1.createHash)('sha256').update(`${type}:${value}`).digest('hex');
22
+ }
23
+ }
24
+ exports.RevokedCredentials = RevokedCredentials;
25
+ //# sourceMappingURL=revoked-credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revoked-credentials.js","sourceRoot":"","sources":["../../src/server/revoked-credentials.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAEzC,kDAA8C;AAE9C,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAElC,MAAa,kBAAkB;IAA/B;QACmB,aAAQ,GAAG,IAAI,oBAAQ,CAAO,WAAW,CAAC,CAAC;IAiB9D,CAAC;IAfC,GAAG,CAAC,UAA0B;QAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,kBAAkB,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;IACtE,CAAC;IAED,GAAG,CAAC,UAA0B;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,kBAAkB,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,KAAK,IAAI,CAAC;IAChF,CAAC;IAED,MAAM,CAAC,UAA0B;QAC/B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,kBAAkB,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;IACnE,CAAC;IAEO,MAAM,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,EAAkB;QACxD,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,CAAC;CACF;AAlBD,gDAkBC"}
@@ -6,12 +6,12 @@ const scraper_api_client_1 = require("../clients/scraper-api-client");
6
6
  const version_1 = require("../version");
7
7
  const tools_1 = require("../tools");
8
8
  class ScraperAPIBaseServer {
9
- constructor({ auth, toolsets = [] }) {
9
+ constructor({ auth, toolsets = [], onAuthenticationError, }) {
10
10
  this.server = new mcp_js_1.McpServer({
11
11
  name: 'decodo',
12
12
  version: version_1.PACKAGE_VERSION,
13
13
  });
14
- this.sapiClient = new scraper_api_client_1.ScraperApiClient({});
14
+ this.sapiClient = new scraper_api_client_1.ScraperApiClient({ onAuthenticationError });
15
15
  this.auth = auth;
16
16
  this.registerTools({ toolsets });
17
17
  this.registerResources();
@@ -1 +1 @@
1
- {"version":3,"file":"sapi-base-server.js","sourceRoot":"","sources":["../../src/server/sapi-base-server.ts"],"names":[],"mappings":";;;AAAA,oEAAoE;AAGpE,sEAAiE;AACjE,wCAA6C;AAC7C,oCA+BkB;AAKlB,MAAa,oBAAoB;IAO/B,YAAY,EAAE,IAAI,EAAE,QAAQ,GAAG,EAAE,EAAiD;QAChF,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAS,CAAC;YAC1B,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,yBAAe;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,GAAG,IAAI,qCAAgB,CAAC,EAAE,CAAC,CAAC;QAE3C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QAEjB,IAAI,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEjC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,SAA+D;QACrE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;IAmCD,aAAa,CAAC,EAAE,QAAQ,EAA2B;QACjD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,oBAAoB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;YACrF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;IACH,CAAC;IAED,gBAAgB;QACd,KAAK,MAAM,IAAI,IAAI,oBAAoB,CAAC,QAAQ,EAAE,CAAC;YACjD,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,gDAAgD;IAClD,CAAC;;AAhFH,oDAiFC;AAxDQ,6BAAQ,GAAW;IACxB,IAAI,4BAAoB,EAAE;IAC1B,IAAI,sBAAc,EAAE;IACpB,IAAI,wBAAgB,EAAE;IACtB,IAAI,qBAAa,EAAE;IACnB,IAAI,sBAAc,EAAE;IACpB,IAAI,wBAAgB,EAAE;IACtB,IAAI,8BAAsB,EAAE;IAC5B,IAAI,wBAAgB,EAAE;IACtB,IAAI,yBAAiB,EAAE;IACvB,IAAI,yBAAiB,EAAE;IACvB,IAAI,yBAAiB,EAAE;IACvB,IAAI,6BAAqB,EAAE;IAC3B,IAAI,yBAAiB,EAAE;IACvB,IAAI,0BAAkB,EAAE;IACxB,IAAI,wBAAgB,EAAE;IACtB,IAAI,yBAAiB,EAAE;IACvB,IAAI,sBAAc,EAAE;IACpB,IAAI,4BAAoB,EAAE;IAC1B,IAAI,6BAAqB,EAAE;IAC3B,IAAI,yBAAiB,EAAE;IACvB,IAAI,2BAAmB,EAAE;IACzB,IAAI,0BAAkB,EAAE;IACxB,IAAI,4BAAoB,EAAE;IAC1B,IAAI,yBAAiB,EAAE;IACvB,IAAI,sBAAc,EAAE;IACpB,IAAI,2BAAmB,EAAE;IACzB,IAAI,sBAAc,EAAE;IACpB,IAAI,sBAAc,EAAE;IACpB,IAAI,mBAAW,EAAE;IACjB,IAAI,sBAAc,EAAE;CACrB,CAAC"}
1
+ {"version":3,"file":"sapi-base-server.js","sourceRoot":"","sources":["../../src/server/sapi-base-server.ts"],"names":[],"mappings":";;;AAAA,oEAAoE;AAGpE,sEAAiE;AAEjE,wCAA6C;AAC7C,oCA+BkB;AAKlB,MAAa,oBAAoB;IAO/B,YAAY,EACV,IAAI,EACJ,QAAQ,GAAG,EAAE,EACb,qBAAqB,GAKtB;QACC,IAAI,CAAC,MAAM,GAAG,IAAI,kBAAS,CAAC;YAC1B,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,yBAAe;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,GAAG,IAAI,qCAAgB,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAElE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QAEjB,IAAI,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEjC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,SAA+D;QACrE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;IAmCD,aAAa,CAAC,EAAE,QAAQ,EAA2B;QACjD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,oBAAoB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;YACrF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;IACH,CAAC;IAED,gBAAgB;QACd,KAAK,MAAM,IAAI,IAAI,oBAAoB,CAAC,QAAQ,EAAE,CAAC;YACjD,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,gDAAgD;IAClD,CAAC;;AAxFH,oDAyFC;AAxDQ,6BAAQ,GAAW;IACxB,IAAI,4BAAoB,EAAE;IAC1B,IAAI,sBAAc,EAAE;IACpB,IAAI,wBAAgB,EAAE;IACtB,IAAI,qBAAa,EAAE;IACnB,IAAI,sBAAc,EAAE;IACpB,IAAI,wBAAgB,EAAE;IACtB,IAAI,8BAAsB,EAAE;IAC5B,IAAI,wBAAgB,EAAE;IACtB,IAAI,yBAAiB,EAAE;IACvB,IAAI,yBAAiB,EAAE;IACvB,IAAI,yBAAiB,EAAE;IACvB,IAAI,6BAAqB,EAAE;IAC3B,IAAI,yBAAiB,EAAE;IACvB,IAAI,0BAAkB,EAAE;IACxB,IAAI,wBAAgB,EAAE;IACtB,IAAI,yBAAiB,EAAE;IACvB,IAAI,sBAAc,EAAE;IACpB,IAAI,4BAAoB,EAAE;IAC1B,IAAI,6BAAqB,EAAE;IAC3B,IAAI,yBAAiB,EAAE;IACvB,IAAI,2BAAmB,EAAE;IACzB,IAAI,0BAAkB,EAAE;IACxB,IAAI,4BAAoB,EAAE;IAC1B,IAAI,yBAAiB,EAAE;IACvB,IAAI,sBAAc,EAAE;IACpB,IAAI,2BAAmB,EAAE;IACzB,IAAI,sBAAc,EAAE;IACpB,IAAI,sBAAc,EAAE;IACpB,IAAI,mBAAW,EAAE;IACjB,IAAI,sBAAc,EAAE;CACrB,CAAC"}
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ScraperAPIHttpServer = void 0;
4
4
  const sapi_base_server_1 = require("./sapi-base-server");
5
5
  class ScraperAPIHttpServer extends sapi_base_server_1.ScraperAPIBaseServer {
6
- constructor({ toolsets = [], auth }) {
7
- super({ auth, toolsets });
6
+ constructor({ toolsets = [], auth, onAuthenticationError, }) {
7
+ super({ auth, toolsets, onAuthenticationError });
8
8
  }
9
9
  }
10
10
  exports.ScraperAPIHttpServer = ScraperAPIHttpServer;
@@ -1 +1 @@
1
- {"version":3,"file":"sapi-http-server.js","sourceRoot":"","sources":["../../src/server/sapi-http-server.ts"],"names":[],"mappings":";;;AAGA,yDAA0D;AAG1D,MAAa,oBAAqB,SAAQ,uCAAoB;IAK5D,YAAY,EAAE,QAAQ,GAAG,EAAE,EAAE,IAAI,EAAiD;QAChF,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5B,CAAC;CACF;AARD,oDAQC"}
1
+ {"version":3,"file":"sapi-http-server.js","sourceRoot":"","sources":["../../src/server/sapi-http-server.ts"],"names":[],"mappings":";;;AAIA,yDAA0D;AAG1D,MAAa,oBAAqB,SAAQ,uCAAoB;IAK5D,YAAY,EACV,QAAQ,GAAG,EAAE,EACb,IAAI,EACJ,qBAAqB,GAKtB;QACC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,qBAAqB,EAAE,CAAC,CAAC;IACnD,CAAC;CACF;AAhBD,oDAgBC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trustProxyFromEnv = void 0;
4
+ const trustProxyFromEnv = (value) => {
5
+ var _a;
6
+ const trimmed = (_a = value === null || value === void 0 ? void 0 : value.trim()) !== null && _a !== void 0 ? _a : '';
7
+ if (!trimmed || trimmed === 'false') {
8
+ return false;
9
+ }
10
+ if (trimmed === 'true') {
11
+ return true;
12
+ }
13
+ if (/^\d+$/.test(trimmed)) {
14
+ return Number(trimmed);
15
+ }
16
+ return trimmed;
17
+ };
18
+ exports.trustProxyFromEnv = trustProxyFromEnv;
19
+ //# sourceMappingURL=trust-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-proxy.js","sourceRoot":"","sources":["../../src/server/trust-proxy.ts"],"names":[],"mappings":";;;AAEO,MAAM,iBAAiB,GAAG,CAAC,KAAyB,EAAc,EAAE;;IACzE,MAAM,OAAO,GAAG,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,EAAE,mCAAI,EAAE,CAAC;IAEpC,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAhBW,QAAA,iBAAiB,qBAgB5B"}