How can I send a POST request to display a message to an html file using axios? - javascript

I'm using the weatherstack API and want to send the current temperature of a given city to a simple form in html using the POST method in express (or axios, if possible).
I tried to use the GET method in axios to consume the API and the POST method in express to send the result once the user enters the city they want in the search bar. The code is the following:
app.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const axios = require('axios');
const access_key = '...'
app.use(bodyParser.urlencoded({extended: false}));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
// Successful GET in the console
// axios.get(`http://api.weatherstack.com/current?access_key=${access_key}&query=Dallas`)
// .then(response => {
// const apiResponse = response.data;
// console.log(`Current temperature in ${apiResponse.location.name} is ${apiResponse.current.temperature}℃`);
// }).catch(error => {
// console.log(error);
// });
// ----The problem-------
app.post('/', async function (req, res) {
const{response} = await axios(`http://api.weatherstack.com/current?access_key=${access_key}&query=${req.body.cityName}`)
res.send(`<p>Current temperature in ${req.body.cityName} is ${response.current.temperature} ℃</p>
<a href = '/'>Back</a>`)
});
//------------------------
app.listen({port: 4000}, () => {
console.log("Server running on localhost:4000");
});
The website
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weatherstack</title>
</head>
<body>
<form action="/" method="post">
<p>Inform the city</p>
<input name="cityName">
<button type="submit">Send</button>
</form>
</body>
</html>
But when I run the server I get this error:
How can I solve that?

Axios return the AxiosResponse object.
export interface AxiosResponse<T = any, D = any> {
data: T;
status: number;
statusText: string;
headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
config: AxiosRequestConfig<D>;
request?: any;
}
the content of your response is within the data object.
const { data } = await axios(
`http://api.weatherstack.com/current?access_key=${access_key}&query=${req.body.cityName}`
);
res.send(
`<p>Current temperature in ${req.body.cityName} is ${data.current.temperature} ℃</p><a href = '/'>Back</a>`
)
Or
const response = await axios(
`http://api.weatherstack.com/current?access_key=${access_key}&query=${req.body.cityName}`
);
res.send(
`<p>Current temperature in ${req.body.cityName} is ${response.data.current.temperature} ℃</p><a href = '/'>Back</a>`
)
I tested this code, and it works fine.

Related

Not able to resolve the Promise on client side JS form express res.json

I am not able to debug or figure out why my request is logging raw HTTP response as shown in the image on the browser console once the expressjs server returns the JSON response. Let me kick in all relevant code and we can talk then
index.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Infinite Scroll</title>
<script src="./infiniteScroll.js" defer></script>
</head>
<body>
<div id="testimonial-container"></div>
</body>
</html>
infiniteScroll.js
async function fetchAndAppendTestimonials(limit = 5, after = 0) {
const testimonials = await fetch('/testimonials');
console.log(testimonials);
}
fetchAndAppendTestimonials(5, 0);
I starting adding server.js incrementally so that I can bypass CORS to call the external API - 'https://api.frontendexpert.io/api/fe/testimonials';
server.js
const express = require('express');
const cors = require('cors');
const path = require('path');
const axios = require('axios');
const app = express();
const port = process.env.PORT || 80;
app.use(cors());
app.use(express.static('public'));
const API_BASE_URL = 'https://api.frontendexpert.io/api/fe/testimonials';
async function fetchTestimonials(limit = 5, after = 0) {
const testimonialUrl = new URL(API_BASE_URL);
testimonialUrl.searchParams.set('limit', limit);
// testimonialUrl.searchParams.set('after', after);
try {
const testimonials = await axios.get(testimonialUrl);
// console.log(testimonials);
return testimonials.data;
} catch (error) {
console.log(error);
return error;
}
}
app.get('/testimonials', async function (req, res) {
const testimonials = await fetchTestimonials(5, 10);
console.log(testimonials);
res.json(testimonials);
});
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/index.html'));
});
app.listen(port, function () {
console.log('Server is running on port', port);
});
So on the client console, I am getting a log of raw HTTP response and not the actual JSON. On the express server function, I am getting the exact response. Don't know what is missing.
const testimonials = await fetch('/testimonials');
console.log(testimonials);
I am not able to debug or figure out why my request is logging raw HTTP response
Well, the first step would be to read the documentation for fetch:
Return value: A Promise that resolves to a Response object.
fetch returns a Response object wrapped in a promise.
You're unwrapping it with await and then logging the Response object.
It has various methods on it (such as the json method to wait for the body data to arrive and process it in various ways.
For example, if you want to get the JSON representation of the response body, you can do the following:
const response = await fetch('/testimonials');
const testimonials = await response.json()
console.log(testimonials);

Axios and expressJs request debugging for external HTTP request

My use case or problem arising might be simple. I am not able to debug or figure out why my request is logging Pending promise. Let me kick in all relevant code and we can talk then
index.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Infinite Scroll</title>
<script src="./infiniteScroll.js" defer></script>
</head>
<body>
<div id="testimonial-container"></div>
</body>
</html>
infiniteScroll.js
async function fetchAndAppendTestimonials(limit = 5, after = 0) {
const testimonialsResponse = await fetch('/testimonials');
const testimonials = testimonialsResponse.json();
console.log(testimonials);
}
fetchAndAppendTestimonials(5, 0);
I starting adding server.js incrementally so that I can bypass CORS to call the external API - 'https://api.frontendexpert.io/api/fe/testimonials';
server.js
const express = require('express');
const cors = require('cors');
const path = require('path');
const axios = require('axios');
const app = express();
const port = process.env.PORT || 80;
app.use(cors());
app.use(express.static('public'));
const API_BASE_URL = 'https://api.frontendexpert.io/api/fe/testimonials';
async function fetchTestimonials(limit = 5, after = 0) {
const testimonialUrl = new URL(API_BASE_URL);
testimonialUrl.searchParams.set('limit', limit);
testimonialUrl.searchParams.set('after', after);
try {
const testimonials = await axios.get(API_BASE_URL);
return testimonials.data;
} catch (error) {
console.log(error);
return error;
}
}
app.get('/testimonials', function (req, res) {
const testimonials = fetchTestimonials(5, 0);
console.log('testimonials', testimonials);
res.json(testimonials);
});
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/index.html'));
});
app.listen(port, function () {
console.log('Server is running on port', port);
});
This is the entire app (w/o package.json and other meta files) so far and what I don't understand is that inside server.js file and fetchTestimonials function, the testimonials returned are Promise { <pending> }. This is evident from the console.log I have after the function call.
Can anyone correct this so that I can return a JSON response back to my client side infiniteScroll.js file?
Tangential but if someone, could add if this is the best approach to allow CORS would be great.
You don't seem to be awaiting fetchTestimonials inside your /testimonials route. By making your route handler async, you can solve the Promise {<pending>}
app.get('/testimonials', async function (req, res) {
try {
const testimonials = await fetchTestimonials(5, 0);
console.log('testimonials', testimonials);
res.json(testimonials);
} catch (error) {
console.log(error);
res.status(500).json({ error: 'Internal Server Error' });
}
});

How can I preview a PDF on the front end using it's data sent from the back-end with Expressjs?

I sent a PDF stored on my back-end using Expressjs.
// FILE: app.js
const express = require('express');
const app = express();
var fs = require('fs');
app.use(express.static('./methods-public'));
app.get('/api/pdf', (req, res, next) => {
const path = './dog.pdf';
if (fs.existsSync(path)) {
res.contentType('application/pdf');
fs.createReadStream(path).pipe(res);
} else {
res.status(500);
console.log('File not found');
res.send('File not found');
}
});
app.listen(5000, () => {
console.log('Server is listening on port 5000....');
});
My front-end received the raw data using Javascript with Axios.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
</head>
<body>
<div class="result"></div>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"
integrity="sha512-bZS47S7sPOxkjU/4Bt0zrhEtWx0y0CRkhEp8IckzK+ltifIIE9EMIMTuT/mEzoIMewUINruDBIR/jJnbguonqQ=="
crossorigin="anonymous"
></script>
<script>
const result = document.querySelector('.result');
const fetchPDF = async () => {
try {
const { data } = await axios.get('/api/pdf');
result.innerHTML = '<h3>' + data + '</h3>';
} catch (error) {
result.innerHTML = `<div class="alert alert-danger">Can't Fetch PDF</div>`;
}
};
fetchPDF();
</script>
</body>
</html>
My front end-knowledge is very limited. I've been struggling to understand how I can use this data to render the pdf then display it within a Canvas.

Error in the url passed when I connect to a weather api

This is my first app doing it with node.js and express. This is a basic app where I connect to an external API to show temperature and take a user input "city and feeling" and show it to the UI. I can't get the URL right. I don't know why.
I ran the app and entered data in the city and feeling text area, I debugged the app.js file and found that when it tries to fetch the URL I'm passing its data it gives the error "400 bad requests". What am I doing wrong?
the server.js
// Setup empty JS object to act as endpoint for all routes
projectData = {};
// Require Express to run server and routes
const express = require('express');
// Start up an instance of app
const app = express();
/* Middleware*/
//body-parser as the middle ware to the express to handle HTTP POST
const bodyParser = require('body-parser');
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
const cors = require('cors');
app.use(cors());
// Initialize the main project folder , this line allows talking between server and client side
app.use(express.static('website'));
// Setup Server
const port = 8000;
const server = app.listen(port , ()=>{console.log(`the server running on localhost: ${port}`);});
//GET function
app.get('/fakeData' , getFakeData); //string represents a url path >> / means home
function getFakeData (req,res) {
// body...
console.log(projectData);
res.send(projectData);
}
var project = [];
app.get('/all', sendData);
function sendData (request, response) {
response.send(project);
console.log(project);
};
//POST function
app.post('/addAnimal' ,addAnimal);
function addAnimal (req,res) {
// body...
newEntry = {
date: req.body.date,
temp: req.body.main.temp,
feeling: req.body.feeling
}
project.push(newEntry)
res.send(project)
console.log(project)
}
website/app.js
/* Global Variables */
//let baseURL = 'http://api.openweathermap.org/data/2.5/weather?q=Egypt&APPID=';
let baseURL = `http://api.openweathermap.org/data/2.5/weather?city=`;
let apiKey = '&APPID=bb95e29dbedc4d929be90b0dd99954e0';
// Create a new date instance dynamically with JS
let d = new Date();
let newDate = d.getMonth()+'.'+ d.getDate()+'.'+ d.getFullYear();
//GET request to handle user input
document.getElementById('generate').addEventListener('click', performAction);
function performAction(e){
//Take user input
//const zipcode = document.getElementById('zip').value; //no
const feeling = document.getElementById('feelings').value;
const city = document.getElementById('zip').value;
//the fake api call
//getAnimal('/fakeAnimalData')
getTemp(baseURL ,city , apiKey )
.then (function(data) {
// body...
console.log(data)
postData('/addAnimal' ,{temp:data.main.temp ,date:newDate, feeling:feeling} )
//updateUI()
})
.then(
updateUI()
)
};
const getTemp = async(baseURL ,city , apiKey)=>{
const res = await fetch(baseURL+city+apiKey)
try{
const data = await res.json();
console.log(data)
return data;
}
catch(error){
console.log("error" , error);
}
}
//make a POST request to our route , POST to store locally user-input data
const postData = async(url='' , data={})=>{
//console.log(data);
const response = await fetch(url , {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
// Body data type must match "Content-Type" header
body: JSON.stringify(data),
});
try {
const newData = await response.json();
console.log(newData);
return newData
}catch(error){
console.log("error", error);
}
}
const updateUI = async () => {
const request = await fetch('/all');
try{
const allData = await request.json()
console.log(allData);
document.getElementById('date').innerHTML = allData[0].date;
document.getElementById('temp').innerHTML = allData[0].temp;
document.getElementById('content').innerHTML = allData[0].feeling;
}catch(error){
console.log("error", error);
}
}
website/index.js
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Weather Journal</title>
<link href="https://fonts.googleapis.com/css?family=Oswald:400,600,700|Ranga:400,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id = "app">
<div class ="holder headline">
Weather Journal App
</div>
<div class ="holder zip">
<label for="zip">Enter Zipcode here</label>
<input type="text" id="zip" placeholder="enter zip code here">
</div>
<div class ="holder feel">
<label for="feelings">How are you feeling today?</label>
<textarea class= "myInput" id="feelings" placeholder="Enter your feelings here" rows="9" cols="50"></textarea>
<button id="generate" type = "submit"> Generate </button>
</div>
<div class ="holder entry">
<div class = "title">Most Recent Entry</div>
<div id = "entryHolder">
<div id = "date"></div>
<div id = "temp"></div>
<div id = "content"></div>
</div>
</div>
</div>
<script src="app.js" type="text/javascript"></script>
</body>
</html>
There seems no issue in your url making. I have opened http://api.openweathermap.org/data/2.5/weather?city=cairo&APPID=bb95e29dbedc4d929be90b0dd99954e0 in browser and its returning HTTP 400 Bad Request as status code and due to 400 status code the browser is telling that the request failed.
Here is response. {"cod":"400","message":"Nothing to geocode"}
The original issue, it seems, is your city parameter that your are sending.
However if you change city parameter in your url to q, it seems to work.
http://api.openweathermap.org/data/2.5/weather?q=cairo&appid=bb95e29dbedc4d929be90b0dd99954e0
Here is response. {"coord":{"lon":31.25,"lat":30.06},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"base":"stations","main":{"temp":295,"feels_like":293.65,"temp_min":294.82,"temp_max":295.15,"pressure":1015,"humidity":64},"visibility":10000,"wind":{"speed":4.1,"deg":290},"clouds":{"all":75},"dt":1584185538,"sys":{"type":1,"id":2514,"country":"EG","sunrise":1584158752,"sunset":1584201751},"timezone":7200,"id":360630,"name":"Cairo","cod":200}

Express how to re-direct json data through different endpoints

I'm pretty new to using express and the responses here on StackOverflow have been very confusing. What I have is JSON data that I am retrieving using app.get(). What I want is to modify this data and send it to my index.html file. I know that I can simply use the fetch function to get the data in my index file from the get endpoint but I need to use both the app.post() and app.put() function.
I'm having trouble understanding your question.
Here's a sample code that uses axios and plain vanilla javascript to get some data from backend and then in frontend, you can modify the data. You can replace axios for fetch and it'll still work.
app.js
const express = require("express");
const bodyParser = require("body-parser");
const port = 8000;
const app = express();
/* Simulating data, a better approach would be to use some storage like MySQL... */
let data = {
name: "Elon Musk",
age: "48",
height: "1.88m"
};
app.use(express.static("public"));
/* body-parser is required so the server can parse the data sent. */
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
/* get the data... */
app.get("/api/mydata", function(req, res) {
return res.json(data);
});
/* this is where the client will post the data */
app.post("/api/newdata", function(req, res) {
data.name = req.body.name;
data.age = req.body.age;
return res.json("OK!");
});
app.listen(port, function() {
console.log("Listening on 8000");
});
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="text" id="name" placeholder="Name..." value="">
<input type="text" id="age" placeholder="Age..." value="">
<button type="button" id="setValues">Change values!</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
<script>
window.addEventListener("load", function() {
axios.get("/api/mydata").then(function(res) {
document.getElementById("name").value = res.data.name;
document.getElementById("age").value = res.data.age;
})
});
document.getElementById("setValues").addEventListener("click", function() {
axios.post("/api/newdata", {
name: document.getElementById("name").value,
age: document.getElementById("age").value
}).then(function(res) {
console.log("Sent!");
})
})
</script>
</body>
</html>
If you have any questions, let me know!

Categories