verifiy json else throw error fetch request - javascript

ExampleObject is an example of what is expected from api endpoint
let ExampleObject={
"id":"",
"name":"",
"Body":""
}
how to make sure that the response has those keys without looping through the response? Response is a json object not an array
function handleError(err) {
//handling error code based
return err
}
export const GetUsers = async({
user,
Following
}, Paging) => {
try {
const response = await fetch(Apiurl, {
method: 'GET',
withCredentials: true,
credentials: 'include',
headers: {
'Authorization': Token,
'Content-Type': 'application/json'
}
})
if (response.status != 200) {
throw ('Error Sending request')
}
const ResponseArray = await response.json();
//Verify object here
if ('Key') {
throw ('error with json')
}
return ResponseArray
} catch (err) {
throw (handleError(err))
};
};
and then I call GetUsers from another module
async function callapi() {
try {
await GetUsers(Object, Paging)
} catch (err) {
}
}

You could use if ("id" in ExampleObject && "name" in ExampleObject && "Body" in ExampleObject) {}

Related

How to set two interceptors in axios

I have two functions that using axios post information to different APIs I created with node and express. Both of them have an interceptor as I get a response from by backend with messages, errors, and other information. Yet when I post the to the second url ("/users/login") the first interceptor still fires off (in the addUser instead of the findUser function) even though it is not in the same function. How do I fix this?
async function addUser(user) {
const config = {
headers: {
"Content-Type": "application/json",
},
};
try {
const interceptorResponse = axios.interceptors.response.use(
(response) => {
if (typeof response.data === "object") {
let success = response.data.registerSuccess;
let errors = response.data.errors;
let data = response.data.data;
let message = response.data.message;
setData(() => {
return { ...data, errors, registerSuccess: success, message };
});
}
return response;
}
);
await axios.post("/users/register", user, config);
axios.interceptors.request.eject(interceptorResponse);
} catch (err) {}
}
async function findUser(user) {
const config = {
headers: {
"Content-Type": "application/json",
},
};
try {
axios.interceptors.response.use((response) => {
console.log(response);
if (typeof response.data === "object") {
let loginSuccess = response.data.data.loginSuccess;
let message = response.data.message;
console.log(response.data);
setData(() => {
return { ...data, loginSuccess, message };
});
}
return response;
});
await axios.post("/users/login", user, config);
} catch (error) {}
}

Nodejs async loop function returns blank [duplicate]

I'm doing requests to my API server to authenticate a user, that's not the problem. The problem is that I don't know why my async function doesn't return anything, and I get an error because the data that I want from this function is undefined.
Don't worry if the error management is ugly and in general I can do this better, I'll do that after fixing this problem.
Utils.js class
async Auth(username, password) {
const body = {
username: username,
password: password
};
let req_uuid = '';
await this.setupUUID()
.then((uuid) => {
req_uuid = uuid;
})
.catch((e) => {
console.error(e);
});
let jwtData = {
"req_uuid": req_uuid,
"origin": "launcher",
"scope": "ec_auth"
};
console.log(req_uuid);
let jwtToken = jwt.sign(jwtData, 'lulz');
await fetch('http://api.myapi.cc/authenticate', {
method: 'POST',
headers: { "Content-Type": "application/json", "identify": jwtToken },
body: JSON.stringify(body),
})
.then((res) => {
// console.log(res);
// If the status is OK (200) get the json data of the response containing the token and return it
if (res.status == 200) {
res.json()
.then((data) => {
return Promise.resolve(data);
});
// If the response status is 401 return an error containing the error code and message
} else if (res.status == 401) {
res.json()
.then((data) => {
console.log(data.message);
});
throw ({ code: 401, msg: 'Wrong username or password' });
// If the response status is 400 (Bad Request) display unknown error message (this sould never happen)
} else if (res.status == 400) {
throw ({ code: 400, msg: 'Unknown error, contact support for help. \nError code: 400' });
}
})
// If there's an error with the fetch request itself then display a dialog box with the error message
.catch((error) => {
// If it's a "normal" error, so it has a code, don't put inside a new error object
if(error.code) {
return Promise.reject(error);
} else {
return Promise.reject({ code: 'critical', msg: error });
}
});
}
Main.js file
utils.Auth('user123', 'admin')
.then((res) => {
console.log(res); // undefined
});
Your Async function must return the last promise:
return fetch('http://api.myapi.cc/authenticate', ...);
or await the result and return it:
var x = await fetch('http://api.myapi.cc/authenticate', ...);
// do something with x and...
return x;
Notice that you donโ€™t need to mix promise syntax (.then) with await. You can, but you donโ€™t need to, and probably shouldnโ€™t.
These two functions do exactly the same thing:
function a() {
return functionReturningPromise().then(function (result) {
return result + 1;
});
}
async function b() {
return (await functionReturningPromise()) + 1;
}
await is not to be used with then.
let data = await this.setupUUID();
or
let data=null;
setupUUID().then(res=> data = res)
I would try something like this:
const postReq = async (jwtToken) => {
const body = {
username: username,
password: password,
};
try {
const res = await fetch('http://api.myapi.cc/authenticate', {
method: 'POST',
headers: { "Content-Type": "application/json", "identify": jwtToken },
body: JSON.stringify(body),
})
if (res) {
if (res.status == 200) {
return res.json();
} else if (res.status == 401) {
const data = res.json();
console.log(data.message)
throw ({ code: 401, msg: 'Wrong username or password' });
} else if (res.status == 400) {
throw ({ code: 400, msg: 'Unknown error, contact support for help. \nError code: 400' });
}
}
} catch (err) {
console.error(err)
}
};
const Auth = async (username, password) => {
const jwtData = {
"origin": "launcher",
"scope": "ec_auth"
};
try {
const req_uuid = await this.setupUUID();
if (req_uuid) {
jwtData["req_uuid"] = req_uuid;
const jwtToken = jwt.sign(jwtData, 'lulz');
return await postReq(jwtToken);
}
} catch (err) {
console.error(err);
};
}

Only attempt to login if the error code is 403

I have don't the API check if the token is expired. I have to make a GET call, if I got the 403, error from the API, then I should re-login.
I attempted:
app.get = async (body) => {
return new Promise((resolve, reject) => {
let user = await user.findOne({
where: {
accountId: body.accountId
}
});
if(user){
body.accessToken = user.accessToken;
} else {
body.accessToken = await app.login();
}
request(
{
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + body.accessToken
},
method: 'GET',
uri: `${config.acs.url}${body.url}`,
json: true
}
)
.then((response) => {
resolve(response);
})
.catch((error) => {
// logger.info(error);
if(error.statusCode == 403){
body.accessToken = await app.login(); <<------------- ๐Ÿž๐Ÿž๐Ÿž
app.get(body);
}
reject(error);
});
});
}
I don't know how else to avoid this error.
SyntaxError: await is only valid in an async function
I already have
app.get = async (body) => { ...
I need to re-login only when I get the 403 code in the error block.
How do I re-structure my code to achieve what I described?
The function used in the Promise is not an async function
Try this snippet
app.get = async (body) => {
let resolve, reject;
const promise = new Promise((re, rj) => {
resolve = re;
reject = rj;
});
let user = await user.findOne({
where: {
accountId: body.accountId
}
});
if(user){
body.accessToken = user.accessToken;
} else {
body.accessToken = await app.login();
}
request(
{
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + body.accessToken
},
method: 'GET',
uri: `${config.acs.url}${body.url}`,
json: true
}
)
.then((response) => {
resolve(response);
})
.catch(async (error) => {
// logger.info(error);
if(error.statusCode == 403){
body.accessToken = await app.login(); <<------------- ๐Ÿž๐Ÿž๐Ÿž
app.get(body);
}
reject(error);
});
return promise;
}

How to run a Node script

I need to be able to run a node script to delete an object from an external API. So I should be able to run this command:
node server.js Customer55555
And it should delete the object.
I have called to the API by using Axios.
const axios = require("axios");
const API = "http://dummy.restapiexample.com/api/v1/employees";
function getAllEmployees() {
axios
.get("http://dummy.restapiexample.com/api/v1/employees")
.then(response => {
// console.log(response.data);
console.log(response.status);
function filterEmployee() {
const employeeData = response.data;
employeeData.filter(employee => {
console.log(employee);
});
// console.log(employeeData);
}
filterEmployee();
})
.catch(error => {
console.log(error);
});
}
function deleteEmployee() {
axios({
method: "DELETE",
url: "http://dummy.restapiexample.com/api/v1/delete/36720",
headers: { "Content-Type": "application/json" }
})
.then(
// Observe the data keyword this time. Very important
// payload is the request body
// Do something
console.log("user deleted")
)
.catch(function(error) {
// handle error
console.log(error);
});
}
// getAllEmployees();
deleteEmployee();
I am able to get an individual object, but I need to figure out how to delete it by running the command above.
You can do something like this:
const axios = require("axios")
const API = "http://dummy.restapiexample.com/api/v1/employees"
async function getAllEmployees(filter = null) {
try {
const response = await axios.get("http://dummy.restapiexample.com/api/v1/employees")
console.log(response.status)
let employeeData = response.data
if (filter) {
// return only employees whose name contains filter.name
employeeData = employeeData.filter(({ employee_name }) => {
return employee_name.toLowerCase().indexOf(filter.name.toLowerCase()) >= 0
})
}
return employeeData
} catch(error) {
console.error(error)
return []
}
}
async function deleteEmployee({ id }) {
if (!id) {
throw new Error('You should pass a parameter')
}
try {
const response = await axios({
method: "DELETE",
url: `http://dummy.restapiexample.com/api/v1/delete/${id}`,
headers: { "Content-Type": "application/json" }
})
console.log("user deleted " + id)
} catch(error) {
// handle error
console.error(error)
}
}
async function main(params) {
const employees = await getAllEmployees({ name: params[0] || '' })
// Returns a promise to wait all delete promises
return Promise.all(employess.map(employee => deleteEmployee(employee)))
}
// process.argv contains console parameters. (https://stackoverflow.com/questions/4351521/how-do-i-pass-command-line-arguments-to-a-node-js-program)
main(process.argv.slice(2)).then(() => {
// returns 0 (Success) (https://stackoverflow.com/questions/5266152/how-to-exit-in-node-js)
process.exit(0)
}).catch(() => {
// returns 1 (error)
process.exit(1)
})
You should adapt this sample to get proper filtering and error reporting.

how to parse json after exception handling promise with isomorphic-fetch

During implementing login feature with React, Redux, isomorphic-fetch, ES6 Babel.
Questions
I do not know how to properly combine promises after the checkstatus promise in order to get parsed JSON data from my server.
what am I doing wrong here?
also, do I need to replace isomorphic-fetch package with other more convenient one?
any suggestion for other package is welcome!
loginAction.js
import * as API from '../middleware/api';
import * as ActionTypes from '../actionTypes/authActionTypes';
import 'isomorphic-fetch';
function encodeCredentials(id, pwd) {
return btoa(`${id}{GS}${pwd}`);
}
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
response;
} else {
const error = new Error(response.statusText);
error.response = response;
throw error;
}
}
function parseJSON(response) {
return response.json();
}
export function loginFailure(error) {
return { error, type: ActionTypes.LOGIN_FAILURE };
}
export function loginSuccess(response) {
return dispatch => {
dispatch({ response, type: ActionTypes.LOGIN_SUCCESS });
};
}
export function loginRequest(id, pwd) {
return {
type: ActionTypes.LOGIN_REQUEST,
command: 'login',
lang: 'en',
str: encodeCredentials(id, pwd),
ip: '',
device_id: '',
install_ver: '',
};
}
export function login(id, pwd) {
const credentials = loginRequest(id, pwd);
return dispatch => {
fetch(`${API.ROOT_PATH}${API.END_POINT.LOGIN}`, {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(credentials),
})
.then(checkStatus)
.then(parseJSON)
.then(data => {
console.log(`parsed data ${data}`);
dispatch(loginSuccess(data));
})
.catch(error => {
console.log(`request failed ${error}`);
});
};
}
In my projects usually, I have a helper function fetchJSON that does all utility logic, such as JSON parsing and status check.
Here it is:
import fetch from 'isomorphic-fetch';
function checkStatus(response) {
if(response.ok) {
return response;
} else {
const error = new Error(response.statusText);
error.response = response;
throw error;
}
}
function parseJSON(response) {
return response.json();
}
export default function enhancedFetch(url, options) {
options.headers = Object.assign({
'Accept': 'application/json',
'Content-Type': 'application/json'
}, options.headers);
if(typeof options.body !== 'string') {
options.body = JSON.stringify(options.body);
}
return fetch(url, options)
.then(checkStatus)
.then(parseJSON);
}
Then you can use it in actions:
import fetchJSON from '../utils/fetchJSON'; // this is the enhanced method from utilities
export function login(id, pwd) {
const credentials = loginRequest(id, pwd);
return dispatch => {
fetchJSON(`${API.ROOT_PATH}${API.END_POINT.LOGIN}`, {
method: 'post',
body: credentials
}).then(data => {
console.log(`parsed data ${data}`);
dispatch(loginSuccess(data));
}).catch(error => {
console.log(`request failed ${error}`);
});
};
}
It helps you to keep actions code clean from some boilerplate code. In big projects with tons of similar fetch calls it is a really must-have thing.
You're doing it right, you just forgot return in checkstatus; you should return the response such that the next promise in the chain can consume it.
Also, it seems that checkstatus is synchronous operation, so it's no need to chain it by .then (although, it's OK if you like it that way), you can write:
fetch(...)
.then(response=>{
checkStatus(response)
return response.json()
})
.then(data=>{
dispatch(loginSuccess(data))
})
.catch(...)
I see no reason to get rid of isomorphic-fetch for now - it seems that it does its job.

Categories