I made an api with a database that stores books and I can get the book on the front-end like this
async function getBooks() {
try {
const response = await fetch("https://node-api-with-books.herokuapp.com/books");
return await response.json();
// console.log(books)
} catch (error) {
console.log("Error", error);
}
}
getBooks().then(book => {
console.log(book);
});
But I want to figure at how to add a book to the api
If I am getting this right and assuming that you configured you Api to accept Post requests then all you have to do is just send a post request to the backend API
async function addBook(bookData) {
try {
const response = await fetch("https://node-api-with-books.herokuapp.com/books", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(bookData),
});
return response.json();
} catch (error) {
console.log("Error", error);
}
}
and on the back end, you will parse the request with your middleware and then you can get the data from req.body
resource
Related
Here's the code in react that I am using to get the data from database.
const getData = async (e) => {
const res = await fetch(`${process.env.REACT_APP_BASE_URL}/edit/${id}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const data = await res.json();
console.log(data);
if (res.status === 422 || !data) {
console.log("Error");
} else {
setValues(data);
console.log("Data Edited successfully");
}
};
useEffect(() => {
getData();
}, []);
Here's the patch request
router.patch("/edit/:id", async (req, res) => {
try {
const { id } = req.params;
const updateUser = await Crud.findByIdAndUpdate(id, req.body, {
new: true,
});
console.log(updateUser);
res.status(201).json(updateUser);
} catch {
res.status(422).json(error);
}
});
I want to update the data in my application but I cannot get the data from the database. So can anyone tell what the problem is
From frontend, you are calling GET request and from your backend, you're receiving as a patch how it works pls do the same method on both hands
I have my function that create requests to get recents tweets by a keyword (I'm using NodeJS), but I need to stop it after 10 tweets, how can I do that? From the twitter api doc I didn't find anything...
Here only mentions the limit but not how to set it
https://developer.twitter.com/en/docs/twitter-api/rate-limits
Here the code:
const rules = [{
value: //keyword
}]
function streamTweets() {
const stream = needle.get(streamURL, {
headers: {
Authorization: `Bearer ${TOKEN}`
}
})
stream.on('data', (data) => {
try {
const json = JSON.parse(data)
console.log(json)
} catch (error) {
}
})
}
(async () => {
let currentRules
try {
currentRules = await getRules()
await deleteRules(currentRules)
await setRules()
} catch (error) {
console.error(error)
process.exit(1)
}
streamTweets()
})()
I have a react native app and a nodejs backend. I'm using refresh and access tokens for authentication. My RN code looks like this (simplified):
const onRequest = (config) => {
console.log('data before request', config.data);
config.headers = {
'Authorization': `Bearer ${accessToken.current}`,
'phosphor-device-id': `${deviceId}`,
'Accept': 'application/json',
};
return config;
};
const onRequestError = (error) => {
Promise.reject(error);
};
const onResponse = (response) => {
return response;
};
const onResponseError = async (error) => {
if (error.response.status === 401 && !oConfig._retry) {
oConfig._retry = true;
return refreshAccessToken().then((token) => {
accessToken.current = token;
apiCall.defaults.headers['Authorization'] = `Bearer ${token}`;
oConfig.headers['Authorization'] = `Bearer ${token}`;
return apiCall.request(oConfig);
})
.catch((error) => {
accessToken.current = null;
setAuth(false);
Promise.reject(error);
});
} else {
return Promise.reject(error);
}
}
apiCall.interceptors.request.use(onRequest, onRequestError);
apiCall.interceptors.response.use(onResponse, onResponseError);
In my nodejs code, I have middleware to check for incoming requests. It looks like this:
app.use((req, res, next) => {
console.log(`${req.method}: ${req.url}`);
if (Object.keys(req.query).length > 0) {
console.log('query params', req.query);
}
if (Object.keys(req.body).length > 0) {
console.log('body params', req.body);
}
next();
});
When the user submits an item with an expired access token, the response is "catched" by the axios response interceptor, and a new access token is generated and send back to the user. This works. Also, with return apiCall.request(oConfig);, the original request is retried. This does not work.
The first time , I get some logs about the request in my server console about the received req.body (thanks to the middleware). In my react native console, I see this body-object also (thanks to console.log('date before request', config.data); So when the request is retried, the full original body/data-object is send again to the server. But the second time, the req.body-object on the server (or what the server receives) is empty. I don't get any output in my node.js-middleware about the req.body-object, and my controller fails because it needs this content.
This only happens with POST requests (and req.body). When a "refresh-access-token" happens with a GET-request, the req.query-object is still complete in the second try.
What can possibly be wrong with this?
Edit: ofc I'm using express.json()
Try using error.config instead of oConfig
const onResponseError = async (error) => {
if (error.response.status === 401 && ! error.config._retry) {
error.config._retry = true;
return refreshAccessToken().then((token) => {
accessToken.current = token;
apiCall.defaults.headers['Authorization'] = `Bearer ${token}`;
error.config.headers['Authorization'] = `Bearer ${token}`;
return apiCall.request(error.config);
})
.catch((error) => {
accessToken.current = null;
setAuth(false);
Promise.reject(error);
});
} else {
return Promise.reject(error);
}
}
I have an application where I first make a post request to an endpoint, let say;
ENDPOINT A
I have another endpoint where I make a GET HTTP request, let say;
ENDPOINT B
The issue now is how do I get the current data I posted to ENDPOINT A, from ENDPOINT B without refreshing the page.
Note: Every thing is working fine just that I need to refresh the page to see the current data I posted, which doesn't make it a reactive application.
Here is part of the code
//Get user requests
useEffect(() => {
fetch('http://localhost:3002/request/me', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': JSON.parse(localStorage.getItem("Some"))
}
}).then(function (res) {
// console.log(res)
return res.json()
}).then(function (datas) {
setState({ datas: datas })
console.log(datas)
}).catch(function (e) {
console.log(e)
})
}, [])
//Create request
const onAdd = (data) => {
fetch('http://localhost:3002/request', {
method: 'POST',
headers: {
'Authorization': JSON.parse(localStorage.getItem("Some"))
},
body: data
}).then(function (res) {
// console.log(res)
return res.json()
}).then(function (data) {
setPost({datas: data})
console.log(data)
}).catch(function (e) {
console.log(e)
})
}
You'll probably need to poll the server on an interval. fetch requests you only get back one response, if the data changes later you won't get any update for that update, meaning you'll need to repeat the request manually.
There are different strategies, probably the most simple one is to poll on an interval:
useEffect(() => {
const performRequest = () => fetch('http://localhost:3002/request/me', ...)
.then(...)
const token = setInterval(performRequest, 5000) // Every 5 seconds?
performRequest(); // Initial request
return () => {
// Don't forget to cleanup the interval when this effect is cleaned up.
clearInterval(token)
}
}, []);
But you can do more fancy stuff if you want more control. You could write this logic in a custom hook with the following API:
const { result, refresh } = useRequestMe()
// When needed, call refresh(). e.g. after a succesful POST request.
const onAdd = (data) => {
fetch('http://localhost:3002/request', ...)
.then(function (res) {
// console.log(res)
return res.json()
}).then(function (data) {
setPost({datas: data})
refresh();
console.log(data)
}).catch(function (e) {
console.log(e)
})
}
I am extremely new to Node, I hope someone can help.
I have 2 APIs that are external to my project.
I want to create a single endpoint in my Node Express server that returns the results from both calls.
How would I do this?
So far I figured out how to call an external resource like this,
app.use('/myapi', function(req, res) {
var url = 'https://some-service.com/api1';
res.setHeader('content-type', 'application/json');
req.pipe(request(url)).pipe(res);
});
This will return the results to my application. What I cant figure out is how to make a second call, then combine the results into an object like this,
{ response1, response2 }
Does anyone know how to do this, or point me in the right direction?
Also is there a way to make sure that both calls succeed before sending a response to my application.
Thanks.
You have to use promise a functionality like this, as the external calls can take their own sweet time. You can wait for the calls to get complete and send the final response.
You can update your route to something like below :
app.use('/myapi', function(req, res) {
var url = 'https://some-service.com/api1';
res.setHeader('content-type', 'application/json');
var responseOne = await CallFirstSystem();
var responseTwo = await CallSecondSystem();
var finalResponse = doSomeLogic(responseOne,responseTwo);
res.send(finalResponse);
});
Create separate functions to call and handle the response
function CallFirstSystem() {
return new Promise(async function (resolve, reject) {
try {
var url = "http://firssytem/api";
var updateResult = [];
await axios.get(url, JSON.stringify(requestPayLoad), {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
}).then(function (response) {
updateResult = innerLogicOne(response);
})
.catch(function (error) {
console.log(error);
});
resolve(updateResult);
} catch (err) {
console.log(err)
} finally {}
}).catch((err) => {
console.log(err)
});
}
function CallSecondSystem() {
return new Promise(async function (resolve, reject) {
try {
var url = "http://secondSystem/api";
var updateResult = [];
await axios.get(url, JSON.stringify(requestPayLoad), {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
}).then(function (response) {
updateResult = innerLogicOne(response);
})
.catch(function (error) {
console.log(error);
});
resolve(updateResult);
} catch (err) {
console.log(err)
} finally {}
}).catch((err) => {
console.log(err)
});
}
I am using axios to call API, you are free to use any other library to call the external system API.
Hope this helps.