I want to create a node server that receives an URL and return the result of the request to that URL.
If I send him https://www.google.com in the request I need to receive the result back.
I want to receive the statusCode, the headers and the body.
I want to be able to receive HTML and JSON or any other type of response.
I was able to modify the statusCode but not the rest, any help would be great.
"use strict";
const fetch = require("node-fetch");
const express = require("express");
const app = express();
app.get("/", async (req, res) => {
const { fetch: requestUrl } = req.query;
if (requestUrl) {
try {
const proxyResponse = await fetch(requestUrl);
res.body = proxyResponse.body;
res.statusCode = proxyResponse.status;
res.send();
} catch (e) {
console.error(e);
res.sendStatus(500);
}
} else {
req.sendStatus(400);
}
});
app.listen(3000, () => {
console.log("listening");
});
I tried to modify the headers using res.set(proxyResponse.headers.raw());
but I get TypeError: Content-Type cannot be set to an Array
Thank you for your help.
const fetch = require("node-fetch");
const app = require("express")();
app.get("/", async (req, res) => {
const {fetch: requestUrl} = req.query;
if (requestUrl) {
try {
const proxyResponse = await fetch(requestUrl);
res.statusCode = proxyResponse.status;
// headers
//get
const headers = Array.from(proxyResponse.headers)
// Be careful about content-encoding header!
.filter(([key]) => !key.includes('content-encoding'))
.reduce((headers, [key, value]) => ({[key]: value, ...headers}), {});
//set
res.set(headers);
// body
//get
const body = await proxyResponse.text();
//set
res.send(body);
} catch (e) {
console.error(e);
res.sendStatus(500);
}
} else {
req.sendStatus(400);
}
});
app.listen(3000, () => console.log("listening"));
Related
I'm trying to send data to the server but when I log it gives me undefined even tho I can log it on the client. I think I'm missing something.
Thanks in Advance!
Client
const handleSubmit = async (e) => {
e.preventDefault()
try{
const response = await axios.post('http://localhost:8000/send', {formData})
console.log(response)
} catch(error){
console.log(error)
}
}
Server
app.post('/send', async (req, res) => {
console.log(req.body)
res.send("ok")
})
//client
const handleSubmit = async (e) => {
e.preventDefault()
const config = {
"headers":{
"Content-Type":"application/json"
}
}
const body = JSON.stringify({
formData
})
try{
const response = await axios.post('http://localhost:8000/send', body, config)
console.log(response)
} catch(error){
console.log(error)
}
}
// server
const express = require("express");
const app = express();
app.use(express.json()); // this is necessary
app.post('/send', async (req, res) => {
console.log(req.body)
res.send("ok")
})
Hope it helps!
remove the object property shorthand, use just formData:
const response = await axios.post('http://localhost:8000/send', formData)
I think you might need to set a header on the request
try adding config object as a 3rd argument
const config = {
headers: {'Content-Type': 'application/json'}
}
const handleSubmit = async (e) => {
e.preventDefault()
try{
const response = await axios.post('http://localhost:8000/send',
{formData}, config)
console.log(response)
} catch(error){
console.log(error)
}
}
I have been working on this issue for 2 days, looked at various pages and cannot find a single solution that would work.
Please only reply if you know how to write them with async await functions and please reply if you know the answer of fetch api. I am not looking for axios solutions for the time being.
I have a backend server which runs on port 8000 of localhost, frontend runs on port 3000. Front end is written in React, backend is written in Node/Express.
I am able to successfully make a GET request from backend server but the POST request fails for some reason with the error "VM942:1 POST http://localhost:8000/frontend-to-backend 500 (Internal Server Error)"
Backend server has this error: SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse ()
// React-To-Node-Connection
// React "App.js" file
// "package.json" file contains this
// "proxy": "http://localhost:8000"
useEffect(() => {
const getBackend = async () => {
const res = await fetch('backend-to-frontend');
const data = await res.json();
if (!res.ok) {
throw new Error(`Cannot get data from backend server. HTTP Status: ${res.status}`);
}
console.log(data.message);
// Prints "Hi from backend!"
}
getBackend();
const postBackend = async () => {
try {
const res = await fetch('http://localhost:8000/frontend-to-backend',
{
method: 'POST',
mode: 'no-cors',
body: JSON.stringify({ message: 'Hi from frontend!' }),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}
);
if (res.ok) {
const data = await res.json();
console.log(data);
}
} catch (error) {
console.error(error);
}
}
postBackend();
}, []);
Now the backend code:
app.get('/backend-to-frontend', (req, res) => {
res.json({ message: 'Hi from backend!' });
});
app.post('/frontend-to-backend', (req, res) => {
try {
const reactMessage = JSON.parse(req.body.data);
console.log(`message: ${reactMessage}`);
} catch (err) {
console.error(err);
}
});
How to fix this? Please help!
Full backend server code can be found here:
const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: true }));
app.get('/backend-to-frontend', (req, res) => {
res.json({ message: 'Hi from backend!' });
});
app.post('/frontend-to-backend', (req, res) => {
try {
const reactMessage = JSON.parse(req.body.data);
console.log(`message: ${reactMessage}`);
} catch (err) {
console.error(err);
}
});
const port = process.env.PORT || 8000;
app.listen(port, function () {
console.log(`Backend server started on port ${port}.`);
});
with no-cors, you can only use simple headers, so you cannot POST JSON (see: Supplying request options)
Try urlencoded:
const postBackend = async() => {
try {
const res = await fetch('http://localhost:8000/frontend-to-backend', {
method: 'POST',
mode: 'no-cors',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'message': 'Hi from frontend!'
})
});
if (res.ok) {
const data = await res.json();
console.log(data);
}
} catch (error) {
console.error(error);
}
}
postBackend();
and on the server, don't parse req.body, as it's already done by middleware:
app.post('/frontend-to-backend', (req, res) => {
console.log('req.body: ', req.body);
try {
const reactMessage = req.body.message;
req.body.data may be an object (check with debugger). If so, you might try to stringify before parsing :
JSON.parse(JSON.stringify(req.body.data))
I finally found the answer, here is my sample code. I did not change the React code that much so it is pretty much same, I removed the no cors section and added cors to Express JS code.
Here is my React code.
// React-To-Node-Connection
// "package.json" file has the following line
// "proxy": "http://localhost:8000"
// React Code
useEffect(() => {
const getBackend = async () => {
const res = await fetch('/backend-to-frontend');
const data = await res.json();
if (!res.ok) {
throw new Error(`Cannot get data from backend server. HTTP Status: ${res.status}`);
}
console.log(data.message);
}
getBackend();
const postBackend = async () => {
try {
await fetch('http://localhost:8000/frontend-to-backend',
{
method: 'POST',
body: JSON.stringify({ message: 'Hi from frontend!' }),
headers: {
'Content-Type': 'application/json'
}
}
);
} catch (err) {
console.error(err);
}
}
postBackend();
}, []);
And here is my Express JS code.
const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: true }));
// Express JS Code
const cors = require('cors');
app.use(express.json());
app.use(cors());
app.get('/backend-to-frontend', (req, res) => {
res.json({ message: 'Hi from backend!' });
});
app.post('/frontend-to-backend', (req, res) => {
try {
console.log(req.body.message);
} catch (err) {
console.error(err);
}
});
const port = process.env.PORT || 8000;
app.listen(port, function () {
console.log(`Backend server started on port ${port}.`);
});
Thanks.
I'm trying to print the data from an axios request to a pug template. I'm having issues with access the data. I'm new to this and I think it has something to do with my data object being passed in to the route.
The Backend
axios.get("https://www.worldometers.info/coronavirus/")
.then(res => {
const data = [];
const $ = cheerio.load(res.data);
$('.maincounter-number').each((index, element) => {
const numberData = $(element).text();
data[0] = {numberData: numberData};
//console.log(data);
});
}).catch(err => {
console.log("Error fetching and parsing data: ", err);
});
app.get("/", (req, res) => {
res.render('index', {title: 'Home', data: data});
});
The front end
p #{data.numberData}
There is problem with scoping. The data variable is bound to local scope.
async function scrapeWorldOMeter(){
try{
const worldOMeterResponse = await axios.get("https://www.worldometers.info/coronavirus/");
const data = [];
const $ = cheerio.load(worldOMeterResponse.data);
$('.maincounter-number').each((index, element) => {
const numberData = $(element).text();
data[0] = {numberData: numberData};
return data[0];
});
}
catch(err){
throw new Error(`Can't scrape WorldOMeter ${err}`)
}
}
app.get("/", async(req, res) => {
const data = await scrapeWorldOMeter()
res.render('index', {title: 'Home', data});
});
I'm trying to get an https.get request to assign data from within the request to a variable outside of the request. I'm also using axios. Within the https.get request, it returns the data I want in the res.on('end'... But I can't figure out how to get that data outside of the res.on('end'... portion of the request. Here is my code:
require('dotenv').config();
const express = require('express');
const {SERVER_PORT} = process.env;
const https = require('https');
const xml2js = require('xml2js');
const parser = new xml2js.Parser({ attrkey: "ATTR" });
const app = express();
app.use(express.json());
app.post('/api/ecb/forex/stats', async(req, res) => {
const {base_currency, base_amount, target_currency} = req.body;
let currencyInfo = https.get("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml", function(res) {
let data = '';
res.on('data', async function(stream) {
data += stream;
});
res.on('end', async function(){
parser.parseString(data, async function(error, result) {
if(error === null) {
return result['gesmes:Envelope'].Cube[0].Cube.forEach(element => {
console.log("at",element.Cube);
return element.Cube;
});;
}
else {
console.log(error);
}
});
});
});
console.log(currencyInfo);
})
const port = SERVER_PORT;
app.listen(port, () => console.log(`Port running on port ${port}`));
I want the value of 'element.Cube;' within the res.on('end"... portion of the https.get request to be assigned to the variable "currencyInfo". What am I doing wrong and how do I fix the code?
You can change your code to something like below, then you have Promise to return:
let currencyInfo = await new Promise((resolve, reject) => {
https.get('https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml', function(res) {
let data = '';
res.on('data', async function(stream) {
data += stream;
});
return res.on('end', async function() {
return parser.parseString(data, async function(error, result) {
if(error === null) {
return result['gesmes:Envelope'].Cube[0].Cube.forEach(element => {
resolve(element.Cube);
});
}
else {
reject(error);
}
});
});
});
});
I am trying to make this simple api with the help of this article .The primary purpose of reading this article is to learn react native but it starts with a server in nodejs .I couldn't get it running correctly .
Here is the link to article link
Here is the code for server.js file
import express from 'express';
import http from 'http';
import giphyapi from 'giphy-api';
import base64 from 'base64-stream';
// Initialize http server
const app = express();
// Register /gif endpoint that returns base64 encoded gif
app.get('/gif', async (req, res) => {
res.json({
gif: await fetchGif(),
});
});
// Launch the server on port 3000
const server = app.listen(3000, () => {
const { address, port } = server.address();
console.log(`Listening at http://${address}:${port}`);
});
// Fetch random GIF url with Giphy API, download and Base64 encode it
export const fetchGif = async () => {
const item = await giphyapi().random('cat');
return await encode(await download(item.data.image_url));
};
// File download helper
const download = async (url) => {
return new Promise((resolve, reject) => {
let req = http.get(url.replace('https', 'http'));
req.on('response', res => {
resolve(res);
});
req.on('error', err => {
reject(err);
});
});
};
// Base64 encode helper
const encode = async (content) => {
let output = 'data:image/gif;base64,';
const stream = content.pipe(base64.encode());
return new Promise((resolve, reject) => {
stream.on('readable', () => {
let read = stream.read();
if (read) {
output += read.toString();
}
else {
resolve(output);
}
});
stream.on('error', (err) => {
reject(err);
});
});
};
the error is occurring because the third-party library "base64-stream" does not have the "encoded" function, it may exist in previous versions.
To solve this problem, you need to change some lines of your code so that your server looks like the code below.
const express = require('express'); // instead of "import express from 'express';"
const http = require('http'); // instead of "import http from 'http';"
const giphyapi = require('giphy-api'); // instead of "import http from 'http';"
const { Base64Encode } = require('base64-stream'); // instead of "import base64 from 'base64-stream';"
// Initialize http server
const app = express();
// Register /gif endpoint that returns base64 encoded gif
app.get('/gif', async (req, res) => {
try {
const gif = await fetchGif();
res.json({ gif });
} catch (error) {
res.status(500).send({ error });
}
});
// Base64 encode helper
const encode = (content) => {
let output = 'data:image/gif;base64,';
const stream = content.pipe(new Base64Encode()); // instead of "const stream = content.pipe(base64.encode());"
return new Promise((resolve, reject) => {
stream.on('readable', () => {
let read = stream.read();
if (read) {
output += read.toString();
}
else {
resolve(output);
}
});
stream.on('error', (err) => {
reject(err);
});
});
};
// Launch the server on port 3000
const server = app.listen(3000, () => {
const { address, port } = server.address();
console.log(`Listening at http://${address}:${port}`);
});
// Fetch random GIF url with Giphy API, download and Base64 encode it
const fetchGif = async () => {
try {
const item = await giphyapi().random('cat');
const image = await download(item.data.image_url);
return await encode(image);
} catch (error) {
console.log('fetchGif', error);
}
};
// File download helper
const download = (url) => {
return new Promise((resolve, reject) => {
let req = http.get(url.replace('https', 'http'));
req.on('response', res => {
resolve(res);
});
req.on('error', err => {
reject(err);
});
});
};
base64-stream doesn't have any function called encode(..).
There are two Classes Base64Encode, Base64Decode which are used to stream.