Search code examples
jsonnode.jsrestdatasourceloopback

Loopback: Send request with json data using REST connector


I would like to fetch data from 3rd party REST Service in my Loopback Application. In order to fetch data from Service I need to authenticate first with login and password. I can test service using curl:

curl -b cookies -c cookies -X POST -d '{"auth": {"username":"MyUser","password":"Secret"}}'  'http://api.awesome.service.com/'

That works great. Tcpdump shows request like that:

Host: http://api.awesome.service.com/
User-Agent: curl/7.47.0
Accept: */*
Cookie: HBFAPI_SESSID=hbapi%3A197887%3A58a3028d12c36%3Anym2
Content-Length: 58
Content-Type: application/x-www-form-urlencoded

{"auth":{"username":"MyUser","password":"Secret"}}

So, I've created datasource first:

{
    "awesome_datasource": {
    "name": "awesome_datasource",
    "baseURL": "https://api.awesome.service.com/",
    "crud": false,
    "connector": "rest",
    "operations": [{
        "template": {
            "method": "POST",
            "url": "http://api.awesome.service.com/auth",
            "form":{
                 "auth": {
                     "username": "{username:string}",
                     "password": "{password:string}"
                 }
            },
            "json": true
        },
        "functions":{
            "login": ["username", "password"]
        }
    }]
  } 
}

I tested that using explorer. No matter what I do, I can't get data in request body formatted as json. With or without json option result is this same, which in tcpdump is:

host: api.awesome.service.com
content-type: application/x-www-form-urlencoded
accept: application/json
content-length: 66 
Connection: close

auth%5Busername%5D=MyUser&auth%5Bpassword%5D=Secret

I've tried pass parameters as 'query', 'form' or 'data' option. Also checked various header content-type options, but no luck so far.

Model is simple without parameters. Base model is 'Model' (no User, because I want to keep it simple as possible)

I was able to find this thread, but it wasn't much help:

https://github.com/strongloop/loopback-connector-rest/pull/12

Any advice will be much appreciated.


Solution

  • Well all you have to do is to use json instead of form there:

    {
        "awesome_datasource": {
        "name": "awesome_datasource",
        "baseURL": "https://api.awesome.service.com/",
        "crud": false,
        "connector": "rest",
        "operations": [{
            "template": {
                "method": "POST",
                "url": "http://api.awesome.service.com/auth",
                "json": {
                     "auth": {
                         "username": "{username:string}",
                         "password": "{password:string}"
                     }
                }
            },
            "functions":{
                "login": ["username", "password"]
            }
        }]
      } 
    }
    

    REST connector tries to mimic request module as much as possible. Basically body, json, form and query(qs in request) do the same thing as the request options but they also accept template strings. Here's the documentation from request with a little modification:

    • query(qs in request) - object containing querystring values to be appended to the uri
    • body - entity body for PATCH, POST and PUT requests. Must be a Buffer, String or ReadStream. If json is true, then body must be a JSON-serializable object.
    • form - when passed an object or a querystring, this sets body to a querystring representation of value, and adds Content-type: application/x-www-form-urlencoded header. When passed no options, a FormData instance is returned (and is piped to request). See "Forms" section above.
    • json - sets body to JSON representation of value and adds Content-type: application/json header. Additionally, parses the response body as JSON.