How do I fetch on an update to a url containing JSON? - javascript

I am running a couple of arduino mini's who send JSON data to a url-path on my website. Currently I have managed to fetch the data just fine, but would like to fetch upon JSON changes to the url, instead of fetching every x seconds.
Code for the fetch part:
async function getMini4 () {
let response = await fetch('/api/sensor/mini4')
let data = await response.json()
return data
}
And the Express that posts the formatted json:
app.get('/api/sensor/mini1', (req, resp, next) => {
resp.send(gyroData1)
})
app.post('/api/sensor/mini1', (req, resp, next) => {
gyroData1 = req.body
resp.send()
})
The fetch works just fine, but I can't seem to find anything on fetching when the url changes.

Are you familiar with websockets ? This protocol allow you to push update from the server to the client and it seems to exactly fit your need.

Related

How to send real time response from server to client using Node.js express

on post request server is generating data after few seconds, these are almost 1000 to 10000 entries. Currently i'm saving data into csv file and it's working fine. how can i pas data to client with json array.
Name and Age variable getting data after few seconds
app.post('/', (req, res) => {
// currently passing to results.csv. its working fine i want to send this real time (Name and age) data to client.
const stream = createWriteStream('./results.csv', { flags: 'a', encoding: 'utf8' })
// Append evaluation from response to file
stream.write(`${Name}, ${Age}\n`)
// example data: Patrick, 32
// End stream to avoid accumulation
stream.end()
})
res.send() only send first row but Name and age variable getting update after after each 10 seconds
app.listen(port, () => {
console.log("App is running on port " + port);
}); ```
To parse data into json array, you would have to read the stream before sending the data. Example:
let rows = []
fs.createReadStream('./results.csv')
.pipe(parse())
.on("error", (error) => console.error(error))
.on("data", (row) => rows.push(row))
.on("end", () => res.send(rows))
But if you want to send the csv file data, do something like this:
return res.sendFile("./results.csv", options, (err) => {
if(error) console.error(error)
console.log("File has been sent")
})
NOTE: The parse() method used in the first example is gotten from the fast-csv package.
Also, using a package like fast-csv makes it easy to write data to the csv file while setting headers:true. Trying to read the data, the parse method has to be informed of the headers already set in order to use those values for the json keys.

Express/axios don't set cookies and headers for response

I have very complicated problem. My project has 2 API's. 1 API is for front-end of my application and 1 is for back-end. How it works, is just I send request from front-end API to back-end API.
Front-end API has URL http://localhost:8080/api/ and back-end API has URL http://localhost:3000.
The problem is front-end API can't get cookies from back-end API.
Here is example, function of front-end API just send request to back-end:
router.get('/test-front-api', async (req, res) => {
const data = await api.get('/test-back-api')
return res.json(data.data)
})
Back-and just sends cookie and some random text:
router.get("/test-back-api", (req, res) => {
res.cookie("test", "cookie")
res.send("Hi from back-end")
})
A here is where I have problem:
router.get('/test-front-api', async (req, res) => {
const data = await api.get('/test-back-api')
console.log(data.headers) // If you do console.log here you will this cookie test
return res.json(data.data)
})
But this cookie is not set in browser.
Let me show one more example. In browser I can just type http://localhost:8080/api/test-front-api and here is result, no cookie:
But, if I type not front-end API endpoint, but back-end, everything works perfect:
I was trying literally everything I found about cors options, axios {withCredentials: true} etc. Nothing works.
I have found one solution, but I don't like it:
router.get('/test-front-api', async (req, res) => {
const data = await api.get('/test-back-api')
// Something like this
res.cookie("test", JSON.stringify(data.headers['set-cookie']))
return res.json(data.data)
})
So, my question is why cookie is no set by front-end endpoint?
I have found not reason of the problem, but solution that seems to be ok. As I said, there are 2 API's - front-end and back-end.
From back-end API I get this cookie, but actually, it makes no sense to send it in header. Why? Because the front-end API will send it back on front.
So, using example above, you can do this, first, just send this cookies in body:
router.get("/test-back-api", (req, res) => {
res.json({cookie: "cookie"})
res.send("Hi from back-end")
})
And then, in front-end API, handle it:
router.get('/test-front-api', async (req, res) => {
const data = await api.get('/test-back-api')
res.cookie("test", data.cookie)
return res.json(data.data)
})
But I still have no idea, why I can send the same headers twice, through back-end API, then front-end API and finally on front.

How to write correct app.get()? (node.js / express / boby-parser)

I create server (node.js / express / boby-parser)
and I need to get array of objects 'users'.
its part of code from server.js file:
let users = [{
name: 'user1',
}];
app.get('/users/', (req, res) => {
const filePath = path.join(pth.dir, 'build', 'index.html');
res.json(users);
res.sendFile(filePath);
});
Its my code from frontend:
const handleResponse = (response) => {
return response.text().then(text => {
const data = text && JSON.parse(text);
if (!response.ok) {
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
return data;
});
};
const getAll = (baseUrl) => {
const requestOptions = {
method: 'GET'
};
return fetch(baseUrl, requestOptions).then(handleResponse);
};
Something wrong with my code at server. (I just dodnt know how to use express server).
when I use getAll function I got JSON text replace my page. Can anyone help? How should I write app.get() in server.js. Or do I need write in server part one app.get() to get page or another app.get() to get JSON data?
Why are you trying to send a file in the response?:
res.sendFile(filePath);
For starters, the response content can either be JSON or a file (or any of a variety of other things of course), but not both. With data like JSON or XML it's possible to combine multiple objects into one larger object for a single response, but this won't work if the content types are entirely different as it is with a file.
Looking at your client-side code, you're not even doing anything with that file. You only read the JSON data:
return response.text().then(text => {
const data = text && JSON.parse(text);
if (!response.ok) {
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
return data;
});
So the simplest approach here would just be to not try to send back the file:
app.get('/users/', (req, res) => {
res.json(users);
});
Edit: Based on comments below, you seem to be struggling with the different requests the client makes to the server. The browser loading the page is one request with one response. If that page includes JavaScript that needs to fetch data, that would be a separate AJAX request with its own response containing just that data.
It’s possible to use JSON (or any data) server-side to populate a page template and return a whole page with the data. For that you’d need to use (or build) some kind of templating engine in the server-side code to populate the page before returning it.
The res.json() represents the HTTP response that an Express app sends when it gets an HTTP request. On the other hand, res.sendFile() transfers the file at the given path.
In both cases, the flow is essentially transferred to client who might have made the request.
So no, you cannot use res.sendFile and res.json together.
var options = {
headers: {
'name': 'user1',
}
};
res.sendFile(path.join(__dirname, 'build', 'index.html'), options);
Thats really the closest you can do to achieve the desired task.

Post data is not being recieved

I am trying to test my newly written api to send messages. It catches a message and sends it to a database. I am using https://apitester.com/ to test it. When I try to read req.body, I get undefined.
SERVER
app.route('/message')
.post(createMessage);
var createMessage = (req, res) => {
console.log(req.body)
var newMessage = new Message(req.body)
mlab.insertDocument({database:'databasename', collectionName:'collectionname', documents:newMessage.getCreatePack()})
.then(result => {
res.json(result)
})
}
When I try to log(req.body), I get undefined
This is the request data. Any help is appreciated
As it turns out, I need body parsing middleware, such as body-parser.

Node.js app receives empty response from GET request to API

I'm new to node.js so I'll try my best to explain the problem here. Let me know if any clerification is needed.
In my node.js application I'm trying to take a code (which was received from the response of the 1st call to an API), and use that a code to make a 2nd request(GET request) to another API service. The callback url of the 1st call is /pass. However I got an empty response from the service for this 2nd call.
My understanding is that after the call back from the 1st call, the function in app.get('/pass', function (req, res).. gets invoked and it sends a GET request. What am I doing wrong here? Many thanks in advance!
Here is the part where I try to make a GET request from node.js server and receive an empty response:
app.get('/pass', function (req, res){
var options = {
url: 'https://the url that I make GET request to',
method: 'GET',
headers: {
'authorization_code': code,
'Customer-Id':'someID',
'Customer-Secret':'somePassword'
}
};
request(options, function(err, res, body) {
console.log(res);
});
});
Im a little confused by what you are asking so ill just try to cover what i think you're looking for.
app.get('/pass', (req, res) => {
res.send("hello!"); // localhost:port/pass will return hello
})
Now, if you are trying to call a get request from the request library when the /pass endpoint is called things are still similar. First, i think you can remove the 'method' : 'GET' keys and values as they are not necessary. Now the code will be mostly the same as before except for the response.
app.get('/pass', (req, res) => {
var options = {
url: 'https://the url that I make GET request to',
headers: {
'authorization_code': code,
'Customer-Id':'someID',
'Customer-Secret':'somePassword'
}
};
request(options, function(err, res, body) {
// may need to JSONparse the body before sending depending on what is to be expected.
res.send(body); // this sends the data back
});
});

Categories