How to add id and body to axios.PUT request? - node.js

I am using axios with REACT and wondering how I can use it to make a put request to update an object through the backend node/express API I have set up.
I need to be able to pass an id and a body and not sure of how to do so.
axios.put('/api/profile', id, body)
.then(response => {
console.log(response.data);
})
.catch(err => {
console.log(err);
});
I do not think this will work as it takes the parameters of put(url, data, {headers})

The pattern for this is to making an axios request using the id of the entity/item that you want to update and return as shown:
axios.put(`/api/profile/${id}`, body); //using string interpolation
axios.put('/api/profile' + id, body); //using string concatenation
Then, on your express/node backend, you have a route that will match with this request's URI path and update that profile with the body. Not sure what you're using for your DB, but in pseudocode it would look like this:
/*
* 1. query profile Model for the specific profile
* 2. make sure to check if foundProfile is undefined or not.
* 3. update profile with body
* 4. Catch on errors
*/
router.put('/api/profile/:id', (req, res, next) => {
Profile.findbyId(req.params.id)
.then(foundProfile => foundProfile.update(req.body))
.catch(next);
})
As mentioned in a comment above, you could do this via the query string, but that would be odd/anti-pattern.

Related

Unable to get data from React App to Node server

So Am unable to make a search function i want to get a variable from search field and show the results that matched but am constantly getting this error
variable undefined when i try to console.log it in the node server
Edit-- i have already changed the axios.post to axios.get
app.get(`/search/`, (req, res) => {
let {name} =req.body
var Desc = name
console.log(name)
var Op= Desc+'%'
const q = "SELECT * FROM taric where Description LIKE ? ";
con.query(q,[Op], (err, search) => {
if (err) {
console.log(err);
return res.json(err);
}
console.log(search);
return res.json(search);
});
});
As you can see you are making POST request from frontend where as there is no POST request route to handle your request. As you have make route of GET for fetching the data from backend you need to make GET request from frontend as well. So you need to do as below:
axios.get(`your_endpoint_route_goes_here`);
instead of this:
axios.post(`your_endpoint_route_goes_here`, requestBodyObj);
HTTP methods are not the same.
You are using app.get in the server while triggering a POST call from your client.
axios.post <-----> app.get
(There is no route for POST call which client is expecting)

node-fetch GET with a parameter

I want to get a url with "username" paramater in it.
How can i do it?
Example:
get url: api/find-username
paramater: username: "exampleusername"
Is it possible with node-fetch module?
Yes, it is possible as node-fetch can construct just about any http GET request the server could want.
What you need to know from the target server is how the username parameter is supposed to be delivered. You can construct the request in node-fetch, but you have to construct it in the way that the target server is expecting (which you have not described).
For example, if the username is supposed to be in a query parameter and you're expecting JSON results, then you might do it like this:
const fetch = require('node-fetch');
// build the URL
const url = "http://someserver.com/api/find-username?username=exampleusername";
fetch(url)
.then(res => res.json())
.then(results => {
console.log(results);
})
.catch(err => {
console.log(err);
});
I will mention that constructing the proper URL is not something you guess on. The doc for your target server has to tell you what type of URL is expected and you must construct a URL that matches what it is expecting. It is typical to put parameters in a query string for a GET request as shown above, but when there is one required parameter, it can also be put in the URL path itself:
const fetch = require('node-fetch');
// build the URL
const url = "http://someserver.com/api/find-username/exampleusername";
fetch(url)
.then(res => res.json())
.then(results => {
console.log(results);
})
.catch(err => {
console.log(err);
});

How to post a url

I am trying to convert an image to a url and then post it to a database using axios.post like this:
this.setState({
file: URL.createObjectURL(event.target.files[0])
})
and then posting it like so:
axios
.post(`http://localhost:4000/items/${this.state.file}
my model is this:
let items = new schema ({
img: String
})
and my post controller:
router.post('/:urlImg', function (req, res) {
let b= new items ({
imageProof: req.params.urlImg
})
the error is basically POST 'url' 404 (Not Found):
xhr.js:184 POST http://localhost:4000/items/blob:http://localhost:3000/9045e921-4e7f-4541-8329-0b9cd65814c6 404 (Not Found)
however the thing to note is if I am using a simple url such as www.google.com, it works. however, I can't use https://
does anyone know how I can resolve this problem? Is there some other way to store and display an image?
You can simply url encode your image url as follow. When you just pass the url without encoding it first it forms a invalid url which contains https in the middle. So you have to encode it before passing
axios
.post(`http://localhost:4000/items/${encodeURIComponent(this.state.file)}
Or
Instead of sending it as a url parameter send it as a body parameter
axios.post('/user', {
urlImg: "http://your/image/url"
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
For 2nd approach you might want to change the backend in order to extract the parameter from the request object.

I can not get data from the json request

I send JSON data to route:
const data=[{name:this.name}]
//qs.stringify(payload)
axios
.post('/users',{name:this.name})
.then(
response => {
console.log(response.data);
}
)
.catch(
// error=>console.log(error)
)
And try get data:
router.post('/', function (req, res, next) {
var data = req.body; // here is your data
var obj=JSON.parse(data);
console.log(obj.toString());
res.toString("ok");
});
And I got error 500.
Why not get the data?
Your client side code is fine, except that the constant named data is entirely unused. On server-side however, req.body almost certainly contains a parsed JSON object (provided you have included a body paring middleware already). If you haven't included any body parsing middleware then req.body would be undefined.
Additionally, the toString() method in res doesn't send any response, it simply returns a string representation of the response.
You would need to make following changes to your code:
Include a body parsing middleware (eg. body-parser) to your express middleware chain, if one isn't already included.
Don't call JSON.parse(req.body). body-parser would already have done that. Calling it again will only throw exception, and return 500.
To convert an Object to JSON string, use JSON.stringify() method. obj.toString() will probably only return [object Object].
Send response using one of .send(), .json(), .end() methods on res. Since you need to send a string back, res.send("ok") seems most appropriate.
The changed code should appear something like this:
router.post('/', function (req, res, next) {
var data = req.body; // here is your data
console.log(JSON.stringify(data));
res.send("ok");
});

Expressjs Firebase React Redux Cannot set headers after they are sent to the client

I've been researching this issue for several hours now and found something odd. Using ExpressJS, Firebase, and React for a small app, and need to call the Firebase Database via the Express Backend, and I also need to make post requests to store data in the database via the Express Backend.
Functionality: I make a post request to the backend to add data to the database. Since Firebase is real time db, the data will immediately reflect on the page.
Problem: The issue is, when I make a post call to the backend and that completes, the page refreshes but the data doesn't show because of this
ERROR: [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
/**
* Add new note to Firebase
* Real-Time Database
*/
app.post('/addNote', (req, res)=> {
var title = req.body.note.title;
var body = req.body.note.body;
var userId= req.body.note.uid;
db.notes.push({
title: title,
body: body,
uid: userId
})
res.send("Success")
})
app.get('/all', (req, res, next)=> {
db.notes.on('value', snapshot => {
return res.send(snapshot.val());
})
})
Possible Solution: I've found that using the code below, I can make a post request, manually refresh the page, and the data will reflect with no header error. I'm trying to code the proper functionality but can't seem to figure out where the code is sending multiple responses with the db.notes.on because I'm only sending res.send one time. The clear difference is (.on listens and updates immediately, while .once requires manual refresh)
/**
* Add new note to Firebase
* Real-Time Database
*/
app.post('/addNote', (req, res)=> {
var title = req.body.note.title;
var body = req.body.note.body;
var userId= req.body.note.uid;
db.notes.push({
title: title,
body: body,
uid: userId
})
res.send("Success")
})
app.get('/all', (req, res, next)=> {
db.notes.once('value', snapshot => {
return res.send(snapshot.val());
})
})
An on("value" listener to Firebase will fire:
straight away with the current value of the data,
and will then later also fire when the data changes.
Since you're sending the data in the response to the client in #1, the response will be closed/finished by the time #2 happens.
By using a once("value" listener this problem doesn't happen, since once() removes the listener after #1.

Resources