Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/http-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ HttpContext.prototype.buildArgs = function(method) {
var val;

var typeConverter = ctx.typeRegistry.getConverter(o.type);
var conversionOptions = SharedMethod.getConversionOptionsForArg(o);

// Turn off sloppy coercion for values coming from JSON payloads.
// This is because JSON, unlike other methods, properly retains types
Expand Down Expand Up @@ -187,8 +188,8 @@ HttpContext.prototype.buildArgs = function(method) {
//
// Use some sloppy typing semantics to try to guess what the user meant to send.
var result = doSloppyCoerce ?
typeConverter.fromSloppyValue(ctx, val) :
typeConverter.fromTypedValue(ctx, val);
typeConverter.fromSloppyValue(ctx, val, conversionOptions) :
typeConverter.fromTypedValue(ctx, val, conversionOptions);

debug('arg %j: %s converted %j to %j',
name, doSloppyCoerce ? 'sloppy' : 'typed', val, result);
Expand Down
23 changes: 20 additions & 3 deletions lib/shared-method.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,10 @@ SharedMethod.prototype.invoke = function(scope, args, remotingOptions, ctx, cb)
var desc = accepts[i];
var name = desc.name || desc.arg;
var uarg = SharedMethod.convertArg(desc, args[name]);
var conversionOptions = SharedMethod.getConversionOptionsForArg(desc);

try {
uarg = validateInputArgument(uarg, desc, ctx);
uarg = validateInputArgument(uarg, desc, ctx, conversionOptions);
} catch (e) {
debug('- %s - ' + e.message, sharedMethod.name);
return cb(e);
Expand Down Expand Up @@ -306,7 +307,7 @@ function escapeRegex(d) {
* @param {Context} ctx Remoting request context.
* @return {*} Coerced argument.
*/
function validateInputArgument(uarg, desc, ctx) {
function validateInputArgument(uarg, desc, ctx, conversionOptions) {
var name = desc.name || desc.arg;

// Verify that a required argument has a value
Expand All @@ -318,7 +319,7 @@ function validateInputArgument(uarg, desc, ctx) {
}

var converter = ctx.typeRegistry.getConverter(desc.type);
var err = converter.validate(ctx, uarg);
var err = converter.validate(ctx, uarg, conversionOptions);
if (err) {
err.message = g.f('Invalid argument %j. ', name) + err.message;
throw err;
Expand Down Expand Up @@ -636,3 +637,19 @@ SharedMethod.prototype.addAlias = function(alias) {
this.aliases.push(alias);
}
};

/**
* build conversion options from remote's' args
*
* @param {Object} arg Definition of accepts/returns argument.
* @returns {Object} Options object to pass to type-converter methods, e.g `validate` or `fromTypedValue`.
*/
SharedMethod.getConversionOptionsForArg = function(arg) {
var options = {};

// option for object coercion to allow Array of objects as well as objects
if (arg.allowArray) {
options.allowArray = arg.allowArray;
}
return options;
};
12 changes: 6 additions & 6 deletions lib/type-registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ TypeRegistry.prototype.registerObjectType = function(typeName, factoryFn) {
assert(typeof factoryFn === 'function', 'factoryFn must be a function');

var converter = {
fromTypedValue: function(ctx, data) {
fromTypedValue: function(ctx, data, options) {
var objectConverter = ctx.typeRegistry.getConverter('object');
var result = objectConverter.fromTypedValue(ctx, data);
var result = objectConverter.fromTypedValue(ctx, data, options);
if (result.error || result.value === undefined || result.value === null)
return result;

Expand All @@ -61,14 +61,14 @@ TypeRegistry.prototype.registerObjectType = function(typeName, factoryFn) {
}
},

fromSloppyValue: function(ctx, value) {
fromSloppyValue: function(ctx, value, options) {
var objectConverter = ctx.typeRegistry.getConverter('object');
var result = objectConverter.fromSloppyValue(ctx, value);
var result = objectConverter.fromSloppyValue(ctx, value, options);
return result.error ? result : this.fromTypedValue(ctx, result.value);
},

validate: function(ctx, value) {
return ctx.typeRegistry.getConverter('object').validate(ctx, value);
validate: function(ctx, value, options) {
return ctx.typeRegistry.getConverter('object').validate(ctx, value, options);
},
};

Expand Down
10 changes: 5 additions & 5 deletions lib/types/any.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ var IS_INT_REGEX = /^\-?(?:[0-9]|[1-9][0-9]*)$/;
var IS_FLOAT_REGEX = /^\-?([0-9]+)?\.[0-9]+$/;

module.exports = {
fromTypedValue: function(ctx, value) {
fromTypedValue: function(ctx, value, options) {
return { value: value };
},

fromSloppyValue: function(ctx, value) {
fromSloppyValue: function(ctx, value, options) {
if (value === 'null' || value === null)
return { value: null };

Expand Down Expand Up @@ -51,17 +51,17 @@ module.exports = {
try {
var result = JSON.parse(value);
debug('parsed %j as JSON: %j', value, result);
return this.fromTypedValue(ctx, result);
return this.fromTypedValue(ctx, result, options);
} catch (ex) {
debug('Cannot parse "any" value %j, assuming string. %s', value, ex);
// no-op, use the original string value
}
}

return this.fromTypedValue(ctx, value);
return this.fromTypedValue(ctx, value, options);
},

validate: function(ctx, value) {
validate: function(ctx, value, options) {
// no-op, all values are valid
},
};
28 changes: 14 additions & 14 deletions lib/types/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function ArrayConverter(itemType) {
this._itemType = itemType;
}

ArrayConverter.prototype.fromTypedValue = function(ctx, value) {
ArrayConverter.prototype.fromTypedValue = function(ctx, value, options) {
if (value === undefined || value === null)
return { value: value };

Expand All @@ -29,7 +29,7 @@ ArrayConverter.prototype.fromTypedValue = function(ctx, value) {
var itemConverter = ctx.typeRegistry.getConverter(this._itemType);

for (var ix in value) {
itemResult = itemConverter.fromTypedValue(ctx, value[ix]);
itemResult = itemConverter.fromTypedValue(ctx, value[ix], options);
itemResult = validateConverterResult(itemResult);
debug('typed item result: %j -> %j as %s',
value[ix], itemResult, this._itemType);
Expand All @@ -41,7 +41,7 @@ ArrayConverter.prototype.fromTypedValue = function(ctx, value) {
return { value: items };
};

ArrayConverter.prototype.fromSloppyValue = function(ctx, value) {
ArrayConverter.prototype.fromSloppyValue = function(ctx, value, options) {
if (value === undefined || value === '') {
// undefined was chosen so that it plays well with ES6 default parameters.
return { value: undefined };
Expand All @@ -51,20 +51,20 @@ ArrayConverter.prototype.fromSloppyValue = function(ctx, value) {
return { value: null };
}

return this._fromTypedValueString(ctx, value) ||
this._fromDelimitedString(ctx, value) ||
this._fromSloppyData(ctx, value);
return this._fromTypedValueString(ctx, value, options) ||
this._fromDelimitedString(ctx, value, options) ||
this._fromSloppyData(ctx, value, options);
};

ArrayConverter.prototype._fromTypedValueString = function(ctx, value) {
ArrayConverter.prototype._fromTypedValueString = function(ctx, value, options) {
if (!looksLikeJsonArray(value))
return null;

// If it looks like a JSON array, try to parse it.
try {
var result = JSON.parse(value);
debug('parsed %j as JSON: %j', value, result);
return this.fromTypedValue(ctx, result);
return this.fromTypedValue(ctx, result, options);
} catch (ex) {
debug('Cannot parse array value %j. %s', value, ex);
var err = new Error(g.f('Cannot parse JSON-encoded array value.'));
Expand All @@ -73,7 +73,7 @@ ArrayConverter.prototype._fromTypedValueString = function(ctx, value) {
}
};

ArrayConverter.prototype._fromDelimitedString = function(ctx, value) {
ArrayConverter.prototype._fromDelimitedString = function(ctx, value, options) {
if (typeof value !== 'string')
return null;

Expand All @@ -93,10 +93,10 @@ ArrayConverter.prototype._fromDelimitedString = function(ctx, value) {
var items = value.split(delims);

// perform sloppy-string coercion
return this.fromSloppyValue(ctx, items);
return this.fromSloppyValue(ctx, items, options);
};

ArrayConverter.prototype._fromSloppyData = function(ctx, value) {
ArrayConverter.prototype._fromSloppyData = function(ctx, value, options) {
if (!Array.isArray(value)) {
// Alright, not array-like, just wrap it in an array on the way out.
value = [value];
Expand All @@ -109,7 +109,7 @@ ArrayConverter.prototype._fromSloppyData = function(ctx, value) {
var itemConverter = ctx.typeRegistry.getConverter(this._itemType);

for (var ix in value) {
itemResult = itemConverter.fromSloppyValue(ctx, value[ix]);
itemResult = itemConverter.fromSloppyValue(ctx, value[ix], options);
itemResult = validateConverterResult(itemResult);
debug('item %d: sloppy converted %j to %j', ix, value[ix], itemResult);
if (itemResult.error)
Expand All @@ -119,7 +119,7 @@ ArrayConverter.prototype._fromSloppyData = function(ctx, value) {
return { value: items };
};

ArrayConverter.prototype.validate = function(ctx, value) {
ArrayConverter.prototype.validate = function(ctx, value, options) {
if (value === undefined || value === null)
return null;

Expand All @@ -129,7 +129,7 @@ ArrayConverter.prototype.validate = function(ctx, value) {
var itemConverter = ctx.typeRegistry.getConverter(this._itemType);
var itemError;
for (var ix in value) {
itemError = itemConverter.validate(ctx, value[ix]);
itemError = itemConverter.validate(ctx, value[ix], options);
if (itemError) return itemError;
}
};
Expand Down
8 changes: 4 additions & 4 deletions lib/types/boolean.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ var debug = require('debug')('strong-remoting:http-coercion');
var g = require('strong-globalize')();

module.exports = {
fromTypedValue: function(ctx, value) {
var error = this.validate(ctx, value);
fromTypedValue: function(ctx, value, options) {
var error = this.validate(ctx, value, options);
return error ? { error: error } : { value: value };
},

fromSloppyValue: function(ctx, value) {
fromSloppyValue: function(ctx, value, options) {
if (value === '' || value === undefined)
return { value: undefined };

Expand All @@ -31,7 +31,7 @@ module.exports = {
return { error: invalidBooleanError() };
},

validate: function(ctx, value) {
validate: function(ctx, value, options) {
if (value === undefined || typeof value === 'boolean')
return null;

Expand Down
8 changes: 4 additions & 4 deletions lib/types/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var debug = require('debug')('strong-remoting:http-coercion');
var g = require('strong-globalize')();

module.exports = {
fromTypedValue: function(ctx, value) {
fromTypedValue: function(ctx, value, options) {
if (value === undefined)
return { value: value };

Expand All @@ -24,7 +24,7 @@ module.exports = {
return error ? { error: error } : { value: result };
},

fromSloppyValue: function(ctx, value) {
fromSloppyValue: function(ctx, value, options) {
if (value === '')
return { value: undefined };

Expand All @@ -34,10 +34,10 @@ module.exports = {
value = +value;
}

return this.fromTypedValue(ctx, value);
return this.fromTypedValue(ctx, value, options);
},

validate: function(ctx, value) {
validate: function(ctx, value, options) {
if (value === undefined)
return null;

Expand Down
10 changes: 5 additions & 5 deletions lib/types/integer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@ var isSafeInteger = require('../number-checks').isSafeInteger;
var numberConverter = require('./number');

module.exports = {
fromTypedValue: function(ctx, value) {
var error = this.validate(ctx, value);
fromTypedValue: function(ctx, value, options) {
var error = this.validate(ctx, value, options);
return error ? { error: error } : { value: value };
},

fromSloppyValue: function(ctx, value) {
fromSloppyValue: function(ctx, value, options) {
var result = numberConverter.fromSloppyValue(ctx, value);
if (result.error)
return result;
return this.fromTypedValue(ctx, result.value);
},

validate: function(ctx, value) {
validate: function(ctx, value, options) {
if (value === undefined)
return null;

var err = numberConverter.validate(ctx, value);
var err = numberConverter.validate(ctx, value, options);
if (err)
return err;

Expand Down
10 changes: 5 additions & 5 deletions lib/types/number.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ var debug = require('debug')('strong-remoting:http-coercion');
var g = require('strong-globalize')();

module.exports = {
fromTypedValue: function(ctx, value) {
var error = this.validate(ctx, value);
fromTypedValue: function(ctx, value, options) {
var error = this.validate(ctx, value, options);
return error ? { error: error } : { value: value };
},

fromSloppyValue: function(ctx, value) {
fromSloppyValue: function(ctx, value, options) {
if (value === undefined || value === '')
return { value: undefined };

var result = +value;
return this.fromTypedValue(ctx, result);
return this.fromTypedValue(ctx, result, options);
},

validate: function(ctx, value) {
validate: function(ctx, value, options) {
if (value === undefined)
return null;

Expand Down
Loading