Skip to content

Commit 530b45a

Browse files
committed
allow specifying origins for functions
1 parent d4a6f36 commit 530b45a

16 files changed

+449
-8
lines changed

lib/gateway.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,23 @@ class Gateway extends EventEmitter {
256256
);
257257
}
258258

259+
__originError__ (req, res, origin, headers = {}) {
260+
headers = this.__createHeaders__(req, headers);
261+
headers['content-type'] = 'application/json';
262+
return this.__endRequest__(
263+
403,
264+
this.__formatHeaders__(headers),
265+
req,
266+
res,
267+
JSON.stringify({
268+
error: {
269+
type: 'OriginError',
270+
message: `Provided origin "${origin}" can not access this resource`,
271+
}
272+
})
273+
);
274+
}
275+
259276
__debugError__ (req, res, message, headers = {}) {
260277
message = message || `You do not have permission to debug this endpoint`;
261278
headers = this.__createHeaders__(req, headers);
@@ -1165,12 +1182,6 @@ class Gateway extends EventEmitter {
11651182
this.log(req, `Request Received (Size ${buffer.length})`);
11661183
this.resolve(req, res, buffer, (err, definition, data, buffer, proxyParameters) => {
11671184

1168-
let headers = {};
1169-
headers['x-execution-uuid'] = req._uuid;
1170-
if (definition && definition.allowOrigin) {
1171-
headers['access-control-allow-origin'] = definition.allowOrigin;
1172-
}
1173-
11741185
if (err) {
11751186
if (err.accessSourceError) {
11761187
return this.__accessSourceError__(req, res, err.message);
@@ -1203,6 +1214,20 @@ class Gateway extends EventEmitter {
12031214
return this.__clientError__(req, res, err.message, err.statusCode || 400);
12041215
}
12051216

1217+
let headers = {};
1218+
headers['x-execution-uuid'] = req._uuid;
1219+
if (definition.origins) {
1220+
if (
1221+
req.headers['origin'] &&
1222+
definition.origins.indexOf(req.headers['origin']) !== -1
1223+
) {
1224+
headers['access-control-allow-origin'] = req.headers['origin'];
1225+
} else {
1226+
headers['access-control-allow-origin'] = '!';
1227+
return this.__originError__(req, res, req.headers['origin'], headers);
1228+
}
1229+
}
1230+
12061231
let [contentType, ...contentTypeParameters] = (req.method === 'GET' || req.method === 'DELETE')
12071232
? ['application/x-www-form-urlencoded']
12081233
: (req.headers['content-type'] || '').split(';');

lib/parser/function_parser.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ FunctionParser.definitionFields = {
268268
},
269269
'description': description => typeof description === 'string',
270270
'metadata': metadata => typeof metadata === 'object' && metadata !== null,
271+
'origins': origins => {
272+
return origins === null || origins === void 0 || Array.isArray(origins);
273+
},
271274
'background': background => {
272275
if (background) {
273276
return background &&

lib/parser/nodejs/comment_definition_parser.js

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const validateParameterName = require('./validate_parameter_name.js');
44

55
const DEFAULT_DEFINITION_FIELD = 'description';
66
const DEFINITION_FIELDS = [
7+
'origin',
78
'background',
89
'keys',
910
'charge',
@@ -121,6 +122,27 @@ class CommentDefinitionParser {
121122
}, acl);
122123
}
123124

125+
getOrigin (values) {
126+
let value = values.join(' ').trim();
127+
let origins = [];
128+
if (!value.match(/^(https?:\/\/)?([a-z0-9\-]{0,255}\.)*?([a-z0-9\-]{1,255})(:[0-9]{1,5})?$/gi)) {
129+
throw new Error([
130+
`Invalid origin: "${value}".`,
131+
` Must be a valid hostname consisting of alphanumeric characters or "-"`,
132+
` separated by ".".`,
133+
` Supported protocols are "http://" and "https://", if left absent both`,
134+
` will be enabled.`
135+
].join(''));
136+
}
137+
if (!value.match(/^https?:\/\//gi)) {
138+
origins.push(`https://${value}`);
139+
origins.push(`http://${value}`);
140+
} else {
141+
origins.push(value);
142+
}
143+
return origins;
144+
}
145+
124146
getBackground (values) {
125147
values = values.join(' ').split(' ');
126148
let mode = values[0].trim() || backgroundValidator.defaultMode;
@@ -129,8 +151,8 @@ class CommentDefinitionParser {
129151
if (modes.indexOf(mode) === -1) {
130152
throw new Error([
131153
`Invalid Background mode: "${mode}". Please specify \`@background MODE\``,
132-
`where MODE is one of: "${modes.join('", "')}" (without quotes).`,
133-
`If no mode is provided, the default "${backgroundValidator.defaultMode}" will be used.`
154+
` where MODE is one of: "${modes.join('", "')}" (without quotes).`,
155+
` If no mode is provided, the default "${backgroundValidator.defaultMode}" will be used.`
134156
].join(''));
135157
}
136158
return {
@@ -365,6 +387,12 @@ class CommentDefinitionParser {
365387
});
366388
} else if (field === 'returns') {
367389
definition.returns = this.getParameter(values, textSchema);
390+
} else if (field === 'origin') {
391+
definition.origins = definition.origins || [];
392+
definition.origins = [].concat(
393+
definition.origins,
394+
this.getOrigin(values)
395+
);
368396
} else if (field === 'background') {
369397
definition.background = this.getBackground(values);
370398
} else if (field === 'acl') {
@@ -397,6 +425,7 @@ class CommentDefinitionParser {
397425
{
398426
name: name,
399427
description: '',
428+
origins: null,
400429
acl: null,
401430
background: null,
402431
keys: [],

lib/parser/nodejs/exported_function_parser.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ class ExportedFunctionParser {
290290
let functionDefinition = this.parseParamsFromFunctionExpression(functionExpression);
291291

292292
let description = commentDefinition.description || '';
293+
let origins = commentDefinition.origins || null;
293294
let background = commentDefinition.background || null;
294295
let charge = isNaN(commentDefinition.charge) ? 1 : commentDefinition.charge;
295296
let streams = commentDefinition.streams || null;
@@ -311,6 +312,7 @@ class ExportedFunctionParser {
311312
},
312313
description: description,
313314
metadata: {},
315+
origins: origins,
314316
background: background,
315317
acl: acl,
316318
keys: keys,

lib/parser/static/static_parser.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class StaticParser {
2424
contentType: mime.getType(filename),
2525
contentLength: buffer.byteLength,
2626
},
27+
origins: null,
2728
background: null,
2829
keys: [],
2930
charge: 0,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Function with an invalid origin
3+
* @origin *.autocode.com
4+
* @returns {string}
5+
*/
6+
module.exports = (callback) => {
7+
8+
return callback(null, 'origin');
9+
10+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Function with an invalid origin
3+
* @origin *
4+
* @returns {string}
5+
*/
6+
module.exports = (callback) => {
7+
8+
return callback(null, 'origin');
9+
10+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Function with an invalid origin
3+
* @origin file://www.autocode.com
4+
* @returns {string}
5+
*/
6+
module.exports = (callback) => {
7+
8+
return callback(null, 'origin');
9+
10+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Function with an valid origin
3+
* @origin autocode.com
4+
* @returns {string}
5+
*/
6+
module.exports = (callback) => {
7+
8+
return callback(null, 'origin');
9+
10+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Function with an valid origin
3+
* @origin http://x.y.z.localhost:8000
4+
* @returns {string}
5+
*/
6+
module.exports = (callback) => {
7+
8+
return callback(null, 'origin');
9+
10+
};

0 commit comments

Comments
 (0)