Skip to content

Loopback standard model REST endpoints automatically round BIGINT params  #2352

@stevegaossou

Description

@stevegaossou

Summary

This one is causing me a lot of pain.

After a lot of debugging it looks like Loopback is automatically assuming an ID value on the URI (e.g. /api/myModel/:id) is a Number.

So something like this:
curl -X GET --header "Accept: application/json" "http://192.168.99.100:3000/api/profiles/5828128208445124611"

Does not work because Loopback is automatically converting the BIGINT value to Number, which rounds 5828128208445124611 to 5828128208445125000.

So the above GET request example, results in an error:

{
  "error": {
    "name": "Error",
    "status": 404,
    "message": "Unknown \"Profile\" id \"4828128208445124611\".",
    "statusCode": 404,
    "code": "MODEL_NOT_FOUND",
    "stack": "Error: Unknown \"Profile\" id \"4828128208445124611\".\n    at Function.convertNullToNotFoundError (/usr/src/app/node_modules/loopback/lib/persisted-model.js:81:17)\n    at invokeRestAfter (/usr/src/app/node_modules/loopback/node_modules/strong-remoting/lib/rest-adapter.js:453:25)\n    at /usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:607:21\n    at /usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:246:17\n    at iterate (/usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:146:13)\n    at /usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:157:25\n    at /usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:248:21\n    at /usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:612:34\n    at interceptInvocationErrors (/usr/src/app/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:681:22)\n    at /usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:154:25\n    at /usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:154:25\n    at /usr/src/app/node_modules/loopback/node_modules/async/lib/async.js:154:25\n    at execStack (/usr/src/app/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:488:7)\n    at RemoteObjects.execHooks (/usr/src/app/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:492:10)\n    at phaseAfterInvoke (/usr/src/app/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:652:10)\n    at runHandler (/usr/src/app/node_modules/loopback/node_modules/loopback-phase/lib/phase.js:135:5)"
  }
}

Enabling debugging output in Loopback shows:

Tue, 17 May 2016 19:52:05 GMT loopback:connector:postgresql SQL: SELECT "user_id","first_name","last_name","email","phone","created_at","updated_at","created_by","updated_by" FROM "user_profile"."profile" WHERE "user_id"=$1 ORDER BY "user_id" LIMIT 1
Parameters: ["4828128208445125000"]

So clearly the value 4828128208445124611 gets rounded into 4828128208445125000.

I verified that this happens right at the beginning, using an operations hook:

  Profile.observe('access', function logQuery(ctx, next) {
    console.log('Context', ctx);
    next();
  });

The output shows the ID is already truncated:

query:
 { where: { userId: '4828128208445125000' },
   limit: 1,
   offset: 0,
   skip: 0 },

Is this a known issue? I couldn't find documentation or bug reports etc. on this.

Custom Remote Method

Btw, adding my own remoteMethod where I have control over the Input Argument (i.e. forcing it to be a string) and then calling findById programmatically works correctly:

  Profile.get = function(id, cb) {
    console.log('ID:', id);
    Profile.findById(id).then(function(profile) {
      console.log('FindById: profile', profile);
      cb(null, profile);
    });
  };
  Profile.remoteMethod(
    'get',
    {
      accepts: [
        {arg: 'id', type: 'string', required: true}
      ],
      http: {path: '/:id/get', verb: 'get'},
      returns: {arg: 'profile', type: 'object'}
    }
  );

You can see above I simply am copying the default findById REST endpoint, only difference is I add get to the end of the URI /api/profiles/:id/get. The logic just defers to Profile.findById().

Calling it:

curl -X GET --header "Accept: application/json" "http://192.168.99.100:3000/api/profiles/4828128208445124611/get"

Works with no issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions