I am trying to create a custom data provider for my API. I am able to login and GET_LIST but unable to process the received data. I have adapted the required output format for the API responses and also included the Content-Range header.
With Postman all headers are returned but they seems to be missing in the "response" I am receiving in the convertHTTPResponse method.
Since headers are emtpy, the list won't appear and showing the error:
Warning: Missing translation for key: "Cannot read property 'hasOwnProperty' of undefined"
Certainly something obvious for experimented devs, please help!
Edit: Fixed it by saving the headers before converting the res.json()
myDataProvider.js
export default (apiUrl, httpClient = fetchUtils.fetchJson) => {
let url = '';
const token = localStorage.getItem('token');
const options = {
headers: new Headers({
Accept: 'application/json',
Authorization: 'Bearer ' + token
}),
};
switch (type) {
case GET_LIST:
{
const {
page,
perPage
} = params.pagination;
const {
field,
order
} = params.sort;
const query = {
sort: JSON.stringify([field, order]),
range: JSON.stringify([
(page - 1) * perPage,
page * perPage - 1,
]),
filter: JSON.stringify(params.filter),
};
url = `${apiUrl}/${resource}?${stringify(query)}`;
break;
}
default:
throw new Error(`Unsupported Data Provider request type ${type}`);
}
let headers;
return fetch(url, options)
.then(res => {
headers = res.headers;
return res.json();
})
.then(response => {
//console.log(headers);
switch (type) {
case GET_LIST:
return {
data: response.data.map(resource => ({ ...resource, id: resource.uuid })),
total: parseInt(headers.get('content-range').split('/').pop(), 10)
};
default:
return {
data: response
};
}
});
};
API call URL:
http://localhost:9000/users?filter={}&range=[0,9]&sort=['uuid','DESC']
Result with Postman:
{
"data": [
{
"uuid": "ff1xxa-ddsa-4232-b453-ed44e4dfc11d",
"email": "fr2r32442231y#domain.net",
"created_at": "2019-03-27T23:11:48.000Z",
"updated_at": "2019-03-27T23:11:48.000Z",
}
"total": 74,
"limit": 9,
"offset": 0,
"order": "DESC",
"sort": "uuid",
"success": true
}
Request Headers with Postman:
Authorization:"Bearer token123"
cache-control:"no-cache"
Postman-Token:"5e0442c7-698d-46e2-8656-50f4b10de970"
User-Agent:"PostmanRuntime/7.6.1"
Accept:"*/*"
Host:"localhost:9000"
cookie:"connect.sid=s%3AmfwRL0cVcIcBhqqGy1w6epkxjEh0nRzr.cP03XewB3Na%2B6esVOvN%2FBE5gL8gQvO%2BbWCIkC5Vbq44"
accept-encoding:"gzip, deflate"
Response Headers with Postman:
Access-Control-Allow-Origin:"*"
Access-Control-Expose-Headers:"Content-Range,X-Content-Range"
X-DNS-Prefetch-Control:"off"
X-Frame-Options:"SAMEORIGIN"
Strict-Transport-Security:"max-age=15552000; includeSubDomains"
X-Download-Options:"noopen"
X-Content-Type-Options:"nosniff"
X-XSS-Protection:"1; mode=block"
Content-Range:"users 0-9/74"
Content-Type:"application/json; charset=utf-8"
Content-Length:"13063"
ETag:"W/"3307-8yJ9evfC/wq64GCJcSnFIwWEGC8""
Date:"Thu, 11 Apr 2019 14:03:13 GMT"
Connection:"keep-alive"
Related
Error: {"errors": ["Please include a case-sensitive header of Authorization: Basic <YOUR-REST-API-KEY-HERE> with a valid REST API key."], "reference": ["https://documentation.onesignal.com/docs/accounts-and-keys#section-keys-ids"]}
I tried as below but error as given above
sendNotification = async (data) => {
const { userId } = await OneSignal.getDeviceState();
const notificationObj = {
contents: { en: "Message Body" },
include_player_ids: [userId],
Authorization: "Basic APIKEY",
headings: { en: 'You have new notification' },
android_channel_id: 'id',
template_id: 'id',
buttons: [{ "id": "open_flat", "text": "OPEN HOSTING", "icon": "ic_menu_share" }],
include_external_user_ids: ["13245-123455"],
};
const jsonString = JSON.stringify(notificationObj);
OneSignal.postNotification(jsonString, (success) => {
console.log("Success:", success);
}, (error) => {
console.log("Error:", error);
});
};
//Sending demo
useEffect(() => {
sendNotification()
})
I am getting the error :
Error: {"errors": ["Please include a case-sensitive header of Authorization: Basic with a valid REST API key."], "reference": ["https://documentation.onesignal.com/docs/accounts-and-keys#section-keys-ids"]}
Few months i tried to send notification with fetch with contenttype and Auth header
You need to replace APIKEY with your actual API key, e.g. your API key is "MY_API_KEY123456", then the header should be Authorization: "Basic MY_API_KEY123456"
FOR ANY ONE HAS THIS ERROR
let headers = {
'Content-Type': 'application/json; charset=utf-8',
Authorization: `Basic '<API-KEY-HERE>'`,
};
let endpoint = 'https://onesignal.com/api/v1/notifications';
let params = {
method: 'POST',
headers: headers,
body: JSON.stringify({
app_id: 'App Id',
include_external_user_ids: [{'userid'},{'userid2'}], --> Optional
headings: { en: 'DATA'},
contents: { en: 'DATA'},
buttons: [{ "id": 'id', "text": 'OPEN', "icon": "ic_baseline_open_in_new_24" }], --> OPTIONAL
data: 'Extra data as json'
}),
};
fetch(endpoint, params).then(res => { console.log('sucess NotiButton') }).catch(error => console.log('error' + error));
I've been grinding this out for awhile but am definitely hard blocked. I want to migrate my program from a deprecated request library to a different one. I chose axios but can't get it to work. All I need to be able to do is make the post request in a similar way that lets me access the response body.
Here is my working deprecated library request code:
const getPage = (apiUrl, size, stagedDateAfter) => {
let options = {
json: true,
body: {
"summary": false,
"sort": [{"stagedDate": "asc"}],
"search_after": [stagedDateAfter],
"queries": [],
"page": {"max": size}
}
};
request.post(apiUrl, options, (error, res, body) => {
if (error) {
return console.log(error)
}
if (!error && res.statusCode === 200 && keepGoing == true) {
if(body.meta.total == 0 || (!body)){
throw("error");
}
/*
Code works from this point, can access body, data, etc
*/
}
}
My failing axios library code:
function checkResponseStatus(res) {
if(res.statusCode === 200 && keepGoing == true) {
return res
} else {
throw new Error(`The HTTP status of the reponse: ${res.status} (${res.statusText})`);
}
}
const headers = {
'Content-Type': 'application/json'
}
const getPage = (apiUrl, size, stagedDateAfter) => {
let options = {
json: true,
body: {
"summary": false,
"sort": [{"stagedDate": "asc"}],
"search_after": [stagedDateAfter],
"queries": [],
"page": {"max": size}
}
};
axios.post(apiUrl, options, headers)
.then(response => {
console.log(response);
if(!response){
checkResponseStatus(response);
}
return response;
})
.catch(error => {
console.log(error.res)
})
.then(data => { //This code doesn't work since response not defined here
if(response.data.status == 200){
console.log(data);
}
});
All I need is to be able to access the response body using axios similarly to how I did with the request library but I'm reading the documentation, api, etc and I just cant seem to get the exact format right.
Solved it! Correct format that lets me access body properly.
let options = {
url: stringURL,
method: 'POST',
json: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
data: {
"summary": false,
"sort": [{"stagedDate": "asc"}],
"search_after": [stagedDateAfter],
"queries": [],
"page": {"max": size}
}
};
axios(options)
.then((response)=>{
//rest of code
Really basic question - I'm calling a twilio function from another twilio function to retrieve the ID of a salesforce record. The following code is what gets returned from one function to another. I'm just trying to "read" the contents of the response to get the ID but can't seem to figure it out. I confirmed that the function returning the response works correctly (contains the right data.)
Help is much appreciated!
responsebody
2020-11-24T19:38:02.642Z 13c8fae2-5f74-40c2-942a-d6aa7ed85c48 INFO Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]:
{ body:
PassThrough {
_readableState: [ReadableState],
readable: true,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object] },
disturbed: false,
error: null },
[Symbol(Response internals)]:
{ url: 'https://coxczsdlk-dffcat-8307.twil.io/sf-get-record',
status: 200,
statusText: 'OK',
headers: Headers { [Symbol(map)]: [Object] },
counter: 0 } }
Here's the code for the function returning this response - this line returns the correct ID - response.body.records[0].Id
const querystring = require('querystring');
const request = require('request');
let globalCallback;
exports.handler = function(context, event, callback) {
globalCallback = callback;
console.log("Starting");
console.log("event: ", event);
run(context.DOMAIN_NAME, event);
};
function run(domain, event){
request({
uri: `https://${domain}/sf-access-token`,
method: 'GET'
}, function (err, res, body) {
if(res.statusCode == 200){
// Received Access Token. Now build and send the request
processRequest(JSON.parse(body), event);
} else{
globalCallback(`Error getting token: ${res.body}`);
}
});
}
function processRequest(sfAuthReponse, event){
// if(validateRequest(event)) {
var options = {
// uri: `${sfAuthReponse.instance_url}/services/data/v43.0/query/?q=SELECT+id+From+${event.objectAPIName}+WHERE+callSID__c='${event.callSID}'`,
uri: `${sfAuthReponse.instance_url}/services/data/v43.0/query/?q=SELECT+id+From+Case+WHERE+callSID__c='1'`,
headers: {
'Authorization': 'Bearer ' + sfAuthReponse.access_token,
'Content-Type': 'application/json',
},
body: event.fields,
json:true,
method: 'GET'
};
request(options, processResponse);
// }
}
function validateRequest(event) {
let valid = false;
let validationMessage;
if(!event.objectAPIName || event.objectAPIName.trim().length === 0) {
validationMessage = "Parameter, objectAPIName, was not set in the JSON Request Body. Provide the SF API Name of the object to create";
} else if (!event.fields) {
validationMessage = "Parameter, fields, was not set in the JSON Request Body. Provide this parameter with a JSON value representing the fields to set when creating the SF object.";
} else {
valid = true;
}
if(!valid) {
globalCallback(validationMessage);
}
return valid; // <== This will always return true since execution is terminated with the callback if invalid
}
function processResponse(error, response, body) {
if (!error && response.statusCode == 200) {
console.log('response.body.records[0].Id');
console.log(response.body.records[0].Id);
// Successfully created new object. Response 201 from successful object creation
//globalCallback(null, response.body.records[0].Id);
globalCallback(null, response);
} else{
console.log("Error: ", error);
console.log("Response: ", response);
console.log(body);
globalCallback(body);
}
}
and here's some of the code for the first function calling the above function, not sure how to dot notation into the response.
fetch('https://casdflk-dsfdsfat-8707.twil.io/sf-get-record', {
headers: {
'Authorization': 'Basic ' + context.ENCODED_TWILIO_CREDS,
'Content-Type': 'application/json'
},
method: 'POST',
body: {
objectAPIName: 'Case',
callSID: '1',
}
// callback(null,sid);
}).then(record => {
console.log('recordbody11');
console.log(record.body);
return record;
It looks like you are using fetch.
Fetch has a method .json() that you need to call on the response.
See the MDN page
Is that your question or did I miss something?
I am trying to perform a simple post request in React Native with a module that I also use for my website.
I have an api.ts file where the following is defined:
import { ajax } from 'rxjs/observable/dom/ajax';
import { AjaxRequest } from 'rxjs/observable/dom/AjaxObservable';
const ApiClient = {
loginUser: (email: string, password: string) => {
let requestBody = {email, password};
let url = `${dotenv.REACT_APP_API_URL}/api/users/login`;
return createRequestOptions(url, HttpOptions.POST, requestBody);
}
}
The request options method is as follows:
const createRequestOptions = (url: string, method: string, requestBody?: object) => {
let requestOptions: AjaxRequest = {
method: method,
url: url,
crossDomain: true,
responseType: 'json',
headers: {
'Content-Type': 'application/json',
}
};
if ((method === HttpOptions.POST || method === HttpOptions.PUT) && requestBody) {
requestOptions.body = requestBody;
}
console.log(requestOptions);
return ajax(requestOptions);
};
The output of the requestOptions is as follows:
Object {
"body": Object {
"email": "myemail#gmail.com",
"password": "mypassword",
},
"crossDomain": true,
"headers": Object {
"Content-Type": "application/json",
},
"method": "POST",
"responseType": "json",
"url": "http://localhost:3001/api/users/login",
}
Finally in my epic I have the following:
const authLoginEpic: Epic = (action$, store) =>
action$.pipe(
ofType(ActionTypes.AUTH_LOGIN_REQUEST),
mergeMap((action: AuthLoginRequest) =>
ApiClient.loginUser(action.payload.username, action.payload.password).pipe(
map((res: any) => {
return AuthLoginReceive.create({response: res.response, email: action.payload.username});
}),
catchError((err) => {
console.log(JSON.stringify(err));
For some reason the catchError is triggered and I have no idea why this may be. The output of the log is:
{"message":"ajax error","name":"AjaxError","xhr":{"UNSENT":0,"OPENED":1,"HEADERS_RECEIVED":2,"LOADING":3,"DONE":4,"readyState":4,"status":0,"timeout":0,"withCredentials":false,"upload":{},"_aborted":false,"_hasError":true,"_method":"POST","_response":"","_url":"http://localhost:3001/api/users/login","_timedOut":false,"_trackingName":"unknown","_incrementalEvents":false,"_requestId":null,"_cachedResponse":null,"_headers":{"content-type":"application/json"},"_responseType":"json","_sent":true,"_lowerCaseResponseHeaders":{},"_subscriptions":[]},"request":{"async":true,"crossDomain":true,"withCredentials":false,"headers":{"Content-Type":"application/json"},"method":"POST","responseType":"json","timeout":0,"url":"http://localhost:3001/api/users/login","body":"{\"email\":\"mymail#gmail.com\",\"password\":\"mypassword\"}"},"status":0,"responseType":"json","response":null}
The Ajax error is not very descriptive. Does anyone what I may be doing wrong?
It seems that this happened due to the simple fact that the api address was set to localhost or 127.0.0.1
Ensure to have set this to your local network IP address!
I have try to user #angular/http to send my api but I got the 401 polyfills error so I change it to #ionic-native/http , but then I got yet another error which is :Error: advanced-http value must be string" so I log my header and it was empty???
The log
"normalizedNames": {},
"lazyUpdate": [
{
"name": "Authorization",
"value": "Basic xxxxxxxx",
"op": "a"
},
{
"name": "Content-Type",
"value": "application/x-www-form-urlencoded",
"op": "a"
}
],
"headers": {},
"lazyInit": {
"normalizedNames": {},
"lazyUpdate": null,
"headers": {}
}
mycode
import { HTTP } from '#ionic-native/http';
constructor(public http: HTTP) {}
login(username, password) {
let body = {
username: username,
password: password
};
let headers = new HttpHeaders();
headers = headers.append('Authorization', 'Basic xxxxxx');
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(apiUrl, body, { headers: headers })
.then(data => {
console.log(data.status);
console.log(data.data); // data received by server
console.log(data.headers);
})
.catch(error => {
console.log(error); // error message as string
});
try this.
add this to your app.module
import { HttpClientModule } from '#angular/common/http';
imports: [
BrowserModule,
HttpClientModule,
IonicModule.forRoot(MyApp)
],
then in your code
//import { HTTP } from '#ionic-native/http';
import { HttpClient } from '#angular/common/http';
constructor(public http: HttpClient) {}
login(username, password) {
let body = {
username: username,
password: password
};
let headers = new HttpHeaders();
headers = headers.append('Authorization', 'Basic xxxxxx');
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(apiUrl, body, { headers: headers })
.subscribe(data => {
console.log(data.status);
console.log(data.data); // data received by server
console.log(data.headers);
})
.catch(error => {
console.log(error); // error message as string
});
thread quite old but might be can help others. Change your headers like below and test.
return this.http.post(apiUrl, body, { headers: 'Content-Type: application/json', Authorization: 'Basic xxx'})....