Consume sequence of REST from same client - javascript

Currently I am consuming REST API which requires sequential call to set authentication.
//Set User
http://localhost:8081/user username
//Get Authentication
http://localhost:8081/password password
The above sequential calls are working perfectly from Browser and Postman. But when I tried to call this from Node JS using axios.get(), server was treating this 2 request as completely different request and throwing an error like "Wrong Auth Sequence".
Is that somehow we need to explicitly mention headers to say that request coming from same client? If yes please help on this.
app.get('/', (req, res) => {
let api = `${Url}/user name ${username}`;
console.log('api - ' + api);
//Set Username
axios
.get(api)
.then(response => {
console.log(response);
response.data.includes('USER SET') ? setPassword() : console.log(res.data);
})
.catch(err => console.log(err));
res.send('Hello Word');
});
setPassword = () => {
let api = `${Url}/password ${password}`;
console.log('api - ' + api);
axios
.get(api)
.then(res => {
console.log('success: ' + res.data);
})
.catch(err => console.log('SetPasswordError' + err));
};

The application you are trying to code for is not really a RESTful API and it is expecting you to keep the connection open for multiple requests.

Related

How to send data (a url string) in express to backend from frontend?

I am trying to build a wikipedia web scraper api and this is my code:
const app = express()
const port = 3000
const url = "https://en.wikipedia.org/wiki/Yeti_Airlines_Flight_691"
axios.get(url).then(async (res) => {
try {
if (res.status == 200) {
const result = // Doing cheerio stuff here
app.get('/', (req, res) => {
res.status(200).send(result)
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
}
} finally {
//
}
});
How can I send url dynamically to backend using express and do some stuff then send result back to frontend?
Client side:
This is a function you define in your frontend. You set a request link, which must be known here on client side and server side. Thus take something like /request. Then use axios to send a request to the server. You can pass any parameters with „dynamic“ Information as you called it. The server will receive these informations and can handle them.
const getData = () => {
// insert your server url here instead, with the /request at the end
const requestLink = `http://localhost:3001/request`;
axios
.get(requestLink, {
params: { url: "wikipedia.de/test123" },
})
.catch((error) => {
// here you can implement error handling
console.log(error);
})
.then((res) => {
// print result, received from the server
console.log(res);
});
};
Server side:
The backend is going to wait for a request to the defined link /request.
If he receives such a request, he is executing the code. The req variable contains your dynamic data, such as the wiki url.
Use res.json to send data back to your frontend.
app.get(`/request`, (req, res) => {
// do something with the request here
console.log(req.query);
// send result to the frontend
res.json({
status: "This could be an answer to the frontend.",
});
});

How to deal with rate limited API services using React/Node.js? (ReferenceError)

Hi I'm new to React and NodeJS and currently I am trying to work my way around pulling from a rate limited API service. My idea is to have NodeJS pull data from the API service every 30 minutes or so and send that to my express "/youtube" endpoint for my frontend to be able to infinitely pull from. However I don't know if this is the best practice and I am also running into an ReferenceError with my code. Any help would be greatly appreciated.
I'm able to console.log(data) so I know the variable is defined but I am unsure on how to pass it to app.get() properly.
ERROR
ReferenceError: data is not defined
CODE
const express = require('express')
const axios = require('axios')
const app = express()
const url = "**Youtube API URL**"
axios.get(url)
.then((response) => {
let data = response.data.items
console.log("Posted data")
console.log(data)
})
.catch(
err => console.log(err)
)
app.get("/youtube", (req,res) => {
res.send(data)
})
app.listen(5000, () => {console.log("server started on port 5000")})
Data is undefined in your route because it is defined within the callback of your axios get callback. Even if it were to be defined prior to the axios call, it would still be undefined because the api call is an async operation...
A simple solution would be to make the axios call within your route callback, and send the response within the axios callback. Although there are tons of coding techniques/patterns to solve this issue, this helps illustrate your problem:
app.get("/youtube", (req,res) => {
axios.get(url)
.then((response) => {
let data = response.data.items
console.log("Posted data")
console.log(data)
res.send(data)
})
.catch(
err => console.log(err)
)
})
Of course, you could create an async function and call it from within the route:
async function makeCall() {
const data = await axios.get(url)
.then((response) => {
let resdata = response.data.items
return resdata
})
.catch(
err => console.log(err)
)
return data;
}
Then in your route:
app.get("/youtube", async (req,res) => {
const data = await makeCall();
res.send(data);
}
Caching the data from the response to be made readily available is another issue altogether...
Thank you everyone for your insight. I've ended up taking the Caching approach to be able to deal with API rate limit of the service that I'm pulling from. I make a call from the API in the beginning of my server.js file and added a setInterval function to pull from the API every 30 minutes to update the data and then store it in a cache.
I then pull that data from the cache and send it to my "/youtube" express endpoint.
Here's my working code in hope that it helps anyone else that runs across the same issues as I have.
server.js
const axios = require('axios')
const NodeCache = require('node-cache')
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
const port = process.env.PORT || 4000
const url = " **Youtube API url** "
const myCache = new NodeCache();
function initialCall(){
axios.get(url)
.then((response) => {
const result = response.data.items
myCache.set("key", result)
console.log("Retrived from API")
})
.catch(
err => console.log(err)
)
}
initialCall()
setInterval(initialCall, 1800000)
app.get("/", (req,res) => {
const welcome = "Welcome"
res.send(welcome)
})
app.get("/youtube", (req,res) => {
if(myCache.get("key")){
res.send(myCache.get("key"))
console.log("Retrieved from cache")
}
})
app.listen(port, () => {console.log(`server started on port: ${port} `)})

how can i send custom sms message with twilio api via express

so im trying to make a simple function in a web that has input and button , and when i click the button twilio api send message with the body of input value life if input is hello the message sent is hello, this is the index.js file which is include the simple function that gonna send the message and i don't know if i should use POST method or get just look
let input = document.querySelector("input").value;
document.querySelector("button").addEventListener("click", whatTheHell);
let whatTheHell = () => {
fetch("/sendSms")
.then((res) => res.json())
.then((res) => console.log(res))
.catch((err) => console.log(err));
};
and this the express.js file that contain the twilio api that gonna send the sms
const express = require("express");
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const accountSid = process.env.accountSid;
const authToken = process.env.authToken ;
const app = express();
const client = require("twilio")(accountSid, authToken);
app.use(express.json());
app.use(express.static("public"));
app.get("/sendSms", (req, res) => {
client.messages
.create({
body: "message from me",
messagingServiceSid: "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
to: "NUMBER",
})
.then((message) => {
res.json({ message: message }).done();
});
});
app.listen(3000, () => {
console.log("Server Started");
});
so what i want here in body: "message from me" is to be something like this body : user.input or something like that , i tried using post method and did req.body.msg and msg is input.value but it dont accept post method .
Twilio developer evangelist here.
I would recommend making this a POST request. You need to update a few things to get your input from the front end to the server. Let's start with the front end.
Instead of getting the input's value straight away, you should wait until the button is clicked to get the value. Then, when it is clicked, you need to make a POST request with the message you want to send in the body of the request. One way to do that is to JSON stringify an object of data.
let input = document.querySelector("input");
document.querySelector("button").addEventListener("click", whatTheHell);
let whatTheHell = () => {
const message = input.value;
fetch("/sendSms", {
method: "POST",
body: JSON.stringify({ message: message }),
headers: {
'Content-Type': 'application/json'
}
})
.then((res) => res.json())
.then((res) => console.log(res))
.catch((err) => console.log(err));
};
Now, on the server side we need to update your endpoint to receive POST requests. You are already using the express JSON parsing middleware, so the message will be available as req.body.message. We can then use that in the request to Twilio.
const express = require("express");
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const accountSid = process.env.accountSid;
const authToken = process.env.authToken ;
const app = express();
const client = require("twilio")(accountSid, authToken);
app.use(express.json());
app.use(express.static("public"));
app.post("/sendSms", (req, res) => {
const message = req.body.message;
client.messages
.create({
body: message,
messagingServiceSid: "MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
to: "NUMBER",
})
.then((message) => {
res.json({ message: message });
})
.catch((error) => {
console.error(error);
res.status(500).json({ error: error.message });
});
});
app.listen(3000, () => {
console.log("Server Started");
});
And that should work.
You can use a query paramater to send the message to your express server and retrieve them in your server as explained here: How to get GET (query string) variables in Express.js on Node.js?.
If you make your method a post method when sending it you also need to make your express from get to post like so: app.get() -> app.post()

Connect to mySql on VPS server eventhough works locally

I have a React front-end, with a Node back-end to connect to mySql for data. It works exactly how I want locally. However, now that I'm moving it to a VPS server, I can't seem to get my configuration correct.
The error I get is: create:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0. It's actually returning HTML, of the page that says it's can't find the page.
I setup an express server with this code:(I do realize I need to move login details to an ENV file... just haven't yet)
const express = require('express');
const mysql = require('mysql2');
const connection = mysql.createPool({
host : 'localhost:3306',
user : 'root',
password : 'xxxxx',
database : 'ppr'
});
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.get('/api/clients/all', function (req, res) {
// Connecting to the database.
connection.getConnection(function (err, connection) {
// Executing the MySQL query (select all data from the 'clients' table).
connection.query("SELECT * FROM clients", function (error, results) {
// If some error occurs, we throw an error.
if (error) throw error;
console.log(results);
res.json(results);
});
});
});
// Starting our server.
app.listen(3001, () => {
console.log('Listening on port http://localhost:3001');
});
I start this running on the server, and it runs. No errors.
But then my React app makes the first api call, and I get the error because it returns HTML instead of the data I'm expecting. Do I need to do something different to make it work in production? I have proxy setup in my local machine which probably makes it work... but what do I change for production?
Here's the API call that works locally, but not on the server if it helps:
componentDidMount() {
fetch('/api/clients/all')
.then(res => res.json())
.then((result) => {
this.setState({ clients: result });
console.log(result);
})
.then(
fetch(`/api/policy/all`)
.then(res => res.json())
.then((result) => {
this.setState({ policies: result });
console.log(result);
})
);
}

How to read data from POST, test it with a condition and send a response back

I'm looking for an easy solution to front-end and back-end communication.
I want to write simple JS front-end client where a user can put a number between 1 an 10 000 to guess the number that server has generated.
So the client job is to send number that user is guessing. The server should test if secretNumber is higher or lower then that provided by the user and it should send back that info.
For now, my server only sends that secret number. I'm getting it inside my client console, so the connection is working.
My question is how should I modify my server code to read the number value from request, test it and then send the right response (example -> your number is higher than the secretNumber)?
This is my server:
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors());
app.use((request, response, next) => {
console.log(request.headers);
next();
});
app.use((request, response, next) => {
request.secretNumber = Math.floor(Math.random() * 10000) + 1;
next();
});
app.get('/', (request, response) => {
response.json({
secretNumber: request.secretNumber
});
});
app.listen(3001, () => console.log("Listening on 3001"));
Here is my front-end JS code (I'm using axios):
export function guessNumber(guessValue) {
return dispatch => {
dispatch({ type: GUESS_NUMBER });
axios
.post('/guess', {
isNumber: guessValue,
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
};
}
And I was here looking for answer, but maybe I'm to inexperiened and I need some real example...
First you need to persist the secretNumber between requests. At the moment you are generating a new value on each request.
Assuming just one client using the backend concurrently, you can do this by generating the secretNumber when the server starts and keep it in memory (assign it to a variable).
Then you can simply use route params to capture the client's guess:
app.get('/guess/:guess', (request, response) => {
const guess = params.guess;
// compare guess with secretNumber and respond accordingly
});
Alternatively you can use the request's body (https://expressjs.com/en/4x/api.html#req.body) instead of route params.

Categories

Resources