Loopback: Send request with json data using REST connector - json

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.

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.

Related

event.body in lambda function is not an object even though application/json header exists

I have an API Gateway / lambda function set up with a LAMBDA_PROXY integration.
I have a POST resource which is sending a JSON object in the body like the following:
{
"version": 123,
"attributes": [
{
"id": 1123,
"type": "integer",
"defaultValue": 88
}
]
}
The POST request is sent with a Content-Type: application/json header.
I expect the lambda function to receive event.body as an object so that I will be able to reference the object like this:
const version = event.body.version;
In fact, this does not work and I am forced to run a JSON.parse() on event.body.
At first I was thinking that the content-type header was not getting to the lambda but then I printed to the log event.headers and the header is in fact there:
{
"Accept": "*/*",
"content-type": "application/json",
"Host": "jfpvip409c.execute-api.eu-west-1.amazonaws.com",
"User-Agent": "curl/7.65.0",
"X-Amzn-Trace-Id": "Root=1-5fe9940a-3f3634ce4ccd26f5211c21d1",
"X-Forwarded-For": "192.118.35.111",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
}
Can somebody please help me understand why this is the case ?
Thanks in advance
nsteiner

multiple accept values in request for wiremock

I'm attempting to write a mock for my api.
To test it correctly I need a request whick allows application/json and / to be accepted.
Which sould work in HTML like this
application/json, */*
When I use this in my wiremock mapping json file, i recieve errors, or with minor changes just "not matching" response.
My Json is build like this
"request": {
"urlPathPattern": "/publish",
"method": "POST",
"headers": {
"Accept": {
"contains": "application/json, */*"
}
},
"bodyPatterns": []
}
I couldn't find any solution, neither on the wiremock docs nor with the help of google, but maybe my description of the problem was just not showing the results I would have needed.
Can anyone enlighten me?
with best regards
As I understand your problem, you need to accept both application/json and */* as Accept header values. I'm assuming that the case where you'd receive something matching */* would interpret those * as wildcards, so some/type would match. In this case, you just want to make sure that the Accept header has some value.
If that is the case, I'd recommend you use matches to do regex matching on the header.
"request": {
"urlPathPattern": "/publish",
"method": "POST",
"headers": {
"Accept": {
"matches": ".*\/.*"
}
},
"bodyPatterns": []
}
If you instead need to match exactly on either application/json or */*, you'd need to do something like...
"request": {
"urlPathPattern": "/publish",
"method": "POST",
"headers": {
"Accept": {
"matches": "(application\/json|\*\/\*)"
}
},
"bodyPatterns": []
}

DocuSign REST API INVALID_CONTENT_TYPE sending envelope from template with application/json

I am using Google Apps Script to make a URL request to https://demo.docusign.net/restapi/v2.1/accounts/ACCOUNT-ID/envelopes (where ACCOUNT-ID is my proper numerical account ID.)
It's being sent with the code UrlFetchApp.fetch(url, params).
params is
{
muteHttpExceptions: true,
method: "POST",
headers: {
Authorization: "Bearer "+jwt,
ContentType: "application/json"
},
payload: payload
}
jwt is a token retrieved from the JWT auth flow at execution time, and payload is
{
"accountId": accountID,
"emailSubject": subject,
"templateId": templateID,
"templateRoles": [{
"email": data['email'],
"name": data['name'],
"roleName": "Seller",
"tabs": {
"textTabs": [
{"tabLabel": "Seller", "value": data['name']},
...
]
}
}],
"status": "sent"
}
Variables used here are defined as expected in a manner consistent with the example given by DocuSign
When I execute this, I get the following response with an HTTP 415.
{"errorCode":"INVALID_CONTENT_TYPE","message":"Content Type specified is not supported."}
I have tried removing the ContentType header, passing the payload as a string, and both at once, to no avail. I also tried providing the GUID instead of the numerical ID for accountID, but it came out the same.
Content type should be specified as
Content-Type (with a -) inside headers object or as contentType inside params or options object. payload should also be JSON.stringifyied.

Routing error with REST API in Clickatell

I am trying to send a SMS using REST API in clickatell.
I tested it using POSTMAN.
I sent the Headers as
POST /rest/message HTTP/1.1
Host: api.clickatell.com
Accept: application/json
Content-Type: application/json
X-Version: 1
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxx
In body
{
"from": ["xxxxxxxxxx"],
"mo": "1",
"text": "Test Message ",
"to": ["xxxxxxxxx"]
}
I get a response as
{
"data": {
"message": [
{
"accepted": true,
"to": "xxxxxxxxxxxxx",
"apiMessageId": "xxxxxxxxxxxxxxxxxxxxxxxxx"
}
]
}
}
But when I check in clickatell account it shows the message is not sent and there is a ROUTING ERROR.
I am getting this error only while using REST API. Using HTTP is works fine.
Can someone help?
You're using MO set to 1, so that means that you are attempting to send from a two-way number. Make sure your two-way number is linked to the REST API integration.

How to Add Labels to Confluence Page via REST

I've been hunting for the correct way to add labels to a confluence page via REST (tags, categories, or whatever they are calling them today)
the documentation simply says "add json to the body" and then shows this example
[{"prefix":"global","name":"label1"},{"prefix":"global","name":"label2"}]
Has anyone successfully done this
You need to POST the JSON body using this endpoint: POST /rest/api/content/{id}/label where the id is the id for the content (page).
Reference: https://docs.atlassian.com/confluence/REST/latest/#content/{id}/label-addLabels
For example:
POST /rest/api/content/{id}/label HTTP/1.1
Host: yourinstance.atlassian.net
Authorization: Basic YaRtsWdg4VzdAzazhib2FyZA==
Content-Type: application/json
Cache-Control: no-cache
[
{
"prefix": "global",
"name": "label1"
},
{
"prefix": "global",
"name": "label2"
}
]