~ I'm using Node 10.9.0 and npm 6.2.0 ~
I have the following app running that allows me to make a request to the same site over http and over https.
var fetch = require('node-fetch')
const express = require('express')
const app = express()
//-- HTTP --
app.get('/test-no-ssl', function(req, res){
fetch('http://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(users => {
res.send(users)
}).catch(function(error) {
res.send(error)
})
})
//-- HTTPS --
app.get('/test-ssl', function(req, res){
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(users => {
res.send(users)
}).catch(function(error) {
res.send(error)
})
})
app.listen(3003, () =>
console.log('Listening on port 3003...')
)
Both of these work fine on my local machine and return the JSON response that Typicode provides. But when I deploy these as a Node app on my web host (FastComet), I get the following results:
HTTP /test-no-ssl - Returns the JSON as expected
HTTPS /test-ssl - Returns the following error:
{
"message" : "request to https://jsonplaceholder.typicode.com/users failed, reason: unable to get local issuer certificate",
"type" : "system",
"errno" : "UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
"code" : "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
}
I searched for this error and tried a couple of the usual fixes, but nothing has helped.
These didn't work:
npm config set registry http://registry.npmjs.org/
npm set strict-ssl=false
Has anyone else run into this on a shared hosting provider (that supports Node) and has been able to get this to work? Perhaps even someone who uses FastComet? The support staff of the host doesn't seem to know what to do either, so I'm at a loss.
Try using the following:
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0
Hosting has probably some issue with list of certificate authorities... as a workaround you could try to ignore certificate validity.
const fetch = require('node-fetch')
const https = require('https')
const express = require('express')
const app = express()
const agent = new https.Agent({
rejectUnauthorized: false
})
//-- HTTP --
app.get('/test-no-ssl', function(req, res){
fetch('http://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(users => {
res.send(users)
}).catch(function(error) {
res.send(error)
})
})
//-- HTTPS --
app.get('/test-ssl', function(req, res){
fetch('https://jsonplaceholder.typicode.com/users', { agent })
.then(res => res.json())
.then(users => {
res.send(users)
}).catch(function(error) {
res.send(error)
})
})
app.listen(3003, () =>
console.log('Listening on port 3003...')
)
Note: this has security implications, making https insecure the same way as http.
Related
I am trying to pass data to my Node.js backend in order to use it in a get request to an API.
For example:
Server.js
const PORT = 8000
const axios = require('axios').default
const express = require('express')
const app = express()
const cors = require('cors')
app.use(cors())
require('dotenv').config()
app.use(express.json())
app.get('/convertedAmount', (req, res) => {
const contentBody = req.body
const options = {
method: 'GET',
url: 'https://currency-converter5.p.rapidapi.com/currency/convert',
params: {format: 'json', from: contentBody.primaryCurrency, to:
contentBody.secondaryCurrency, amount: contentBody.primaryCurrencyAmount},
headers: {
'x-rapidapi-host': process.env.RAPIDAPI_HOST,
'x-rapidapi-key': process.env.RAPIDAPI_KEY,
},
}
axios
.request(options)
.then((response) => {
res.json(response.data)
})
.catch((error) => {
console.error(error)
})
})
app.listen(PORT, () => console.log(`server running on PORT ${PORT}`))
The issue is, I don't know how to pass data to the backend from the frontend, without making it a POST request. But that doesn't work if I make a POST request to the rapidAPI url. So the backend needs to stay the same.
My question is, how would I write the frontend part for this?
Using a POST request in the frontend sends the data with the req.body, but I cant get the data to display in my browser on localhost:8000/convertedAmount.
Thank you
My attempt is:
Frontend.js
...
axios.post('/convertedAmount', {
primaryCurrency: 'USD',
secondaryCurrency: 'GBP',
primaryCurrencyAmount: 1
})
.then((response) => {
console.log(response);
}, (error) => {
console.log(error);
})
...
You shouldn't be trying to send data in the body (such as in req.body) through a GET request. That is what a POST request is for.
With a GET request, you should pass data (such as a user id) as a parameter. Basically, in the url string.
FRONTEND
axios.get("/convertedAmount/USD/GBP/1")
BACKEND
app.get("/convertedAmount/:primaryCurrency/:secondaryCurrency/:primaryCurrencyAmount", (req, res)=>{
console.log(req.params.primaryCurrency);
console.log(req.params.secondaryCurrency);
console.log(req.params.primaryCurrencyAmount);
});
Alternatively, you could use query strings, which would look like this:
FRONTEND
axios.get("/convertedAmount?primaryCurrency=USD&secondaryCurrency=GBP&primaryCurrencyAmount=1")
BACKEND
app.get("/convertedAmount*", (req, res)=>{
console.log(req.query.primaryCurrency);
console.log(req.query.secondaryCurrency);
console.log(req.query.primaryCurrencyAmount);
});
I'm new react and nodejs and full stack development in general. I'm trying to make a login page in nodejs/react/mysql. Right now, I'm just trying to do get request for the main login page. I think I'm struggling with connecting the front and backend and the moment.
Nodejs app.js:
const express = require('express');
const bodyparser = require('body-parser');
const cors = require('cors');
const app = express();
const mysql = require('mysql');
let connection = mysql.createConnection({
//Connection is encrypted for security reasons.
host: '***********',
user: '***********t',
password: '***********',
database: '***********'
});
connection.connect(function(err) {
if (err) {
return console.error('error: ' + err.message);
}
console.log('Connected to the MySQL server.');
});
app.listen(3001, () => { console.log('running on port 3001'); });
app.use(cors());
app.use(express.json()); a
app.use(bodyparser.urlencoded({extended: true}));
app.get('/', (req, res) => { res.send('respond with a resource'); });
componentDidMount() react code/fetch request:
componentDidMount() {
// GET request using fetch with error handling
fetch('/')
.then(async response => {
const data = await response.text();
// console.log(data);
console.log('test',data);
// check for error response
if (!response.ok) {
// get error message from body or default to response statusText
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
this.setState({ totalReactPackages: data.total })
})
.catch(error => {
this.setState({ errorMessage: error.toString() });
console.error('There was an error!', error);
});
}
My sql connection works fine, I think it's an issues connecting the front end and backend. Changing following line:.
const data = await response.text();
to:
const data = await response.json();
Returns the following error:
There was an error! SyntaxError: Unexpected token < in JSON at position 0
This is the html it returns in the following screenshot:
Once I figure out how to connect the front end and backend the rest of the project should be easyish to do. The react UI work and my SQl connection works fine. Any help would be greatly appreciated.
You're currently fetching data from the primary site, not the Node.js site you've created.
You should change the fetch to:
fetch('http://localhost:3001')
Additional information
The response you are sending from the backend isn't JSON:
res.send('respond with a resource');
To send JSON, you should use:
res.json({ message: "respond with a resource" });
Then you'll be able to use:
const data = await response.json();
And access the data via:
const message = data.message;
For me it worked just by appending "Https://" to the beginning of the API url.
fetch(`https://api.openweathermap.org/data/2.5/weather?q=${CITY_NAME}&appid=${API_KEY}`)
It took me days and 10s of articles/SO threads to figure out that when doing dev on your local machine the fetch request gets routed to local html document.
I deployed my MERN project on heroku app but when I tried to submit my form it send me this error in console:
Access to XMLHttpRequest at 'localhost:8000/api/products' from origin
'https://thebeuter.herokuapp.com' has been blocked by CORS policy:
Cross origin requests are only supported for protocol schemes: http,
data, chrome, chrome-extension, https. Form.jsx:69 Error: Network
Error
at e.exports (createError.js:16)
at XMLHttpRequest.d.onerror (xhr.js:83)
Here is my server.js:
const express = require("express"),
app = express(),
cors = require("cors"),
port = process.env.PORT || 8000,
db = "beuter",
path = require("path"),
server = app.listen(port, () => console.log(`Listening to on port ${port}`));
app.use(cors());
app.use(express.json());
if (process.env.NODE_ENV === "production") {
app.use(express.static('beuter/build'))
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'beuter', 'build', 'index.html'));
})
}
console.log(port)
require("./server/config/database.config")(db);
require("./server/routes/product.route")(app);
and here is my Form.jsx:
const addProduct = (e) => {
e.preventDefault();
const product = {
title,
title_url,
price,
description1,
description2,
description3,
description4,
description5,
img_url1,
img_url2,
img_url3,
img_url4,
size,
size2,
fit,
fit2,
category,
};
axios
.post("localhost:8000/api/products", product)
.then((res) => {
if (res.data.errors) {
setErrors(res.data.errors);
} else {
navigate("/");
}
})
.catch((err) => console.log(err));
};
return (
...
...
...
)
How can I fix this?
Here is my project github:
https://github.com/nathannewyen/the-beuter
Thank you!
Updated:
ShopAllProducts.jsx:
useEffect(() => {
const fetchItems = async () => {
setLoading(true);
const res = await axios.get("http://localhost:8000/api/products");
setProducts(res.data);
setLoading(false);
};
document.title = `Shop - The Beuter`;
fetchItems();
}, [props]);
the answer for this question is to have env files for development and production
for development
create the file called .env.development in the root folder of your frontend app
in .env.development add this line
REACT_APP_BASE_URL="http:localhost:5000"
and in .env.production add another line as
REACT_APP_BASE_URL="https://algorithammer.herokuapp.com"
or your website (here i am showing the sample)
now make sure that you have a variable called baseURL as global variable
example:
authAPI.js (example)
exports.baseURL = process.env.REACT_APP_BASE_URL;
in Login.js (example)
import {baseURL} from "./authAPI.js"
axios
.post(`${baseURL}/login`, {
data: "sample data"
})
.then((res) => console.log(res))
.catch((err) => console.log(err));
dont forget to push the changes and deploy the heroku app again
I am new to Node, and I can't pass request parameters when using http-proxy-middleware..
It throws me 404 error
This is the express listener:
app.put("/api/markets/:id",()=>{..code..});
This is the axios PUT request:
axios
.put("/api/markets/" + idToPass, {..Object..})
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
And this is the proxyMiddleware:
const proxy = require("http-proxy-middleware");
module.exports = function(app) {
app.use(proxy("/api/*", { target: "http://localhost:3050" }));
};
My client runs on localhost:3000 (react app)
And my server is on localhost:3050
When I open my browser network tab to inspect requests I see that call is being made to
localhost:3000/api/markets/idContent
not
localhost:3050/api/markets/idContent
as it is supposed to.
It works when I send it manually to
localhost:3050/api/markets/idContent
How can I fix this, any ideas?
Thx in advance
It seems the problem is with the proxy configuration. As of now it matches urls only one level deep.
Try /api or /api/** instead
const proxy = require("http-proxy-middleware");
module.exports = function(app) {
app.use(proxy("/api", { target: "http://localhost:3050" }));
};
You are not specifying the base URL. Create an axios instance and specify the correct base URL:
const instance = axios.create({
baseURL: 'http://localhost:3050'
});
And then make every axios requests using that instance:
instance
.put("/api/markets/" + idToPass, {..Object..})
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
I'm relatively new to React, and trying to deploy an application to an Openshift environment. The app consists of a React JS front-end which makes API calls to a nodejs back end restful api. That's the idea at least.
Most of the ways I've found suggest using docker, but I have no idea where to start with that. The create-react-app documentations gives an example of an Node/Express server to render the index.html, which I am much more familiar with and have got working, but I can't seem to set a proxy to route the api calls to the back-end.
I initially tried setting the proxy in the package.json, but that didn't work. I then found express-http-proxy which looked promising, but can't get it to work.
My front end server looks like this:
const express = require('express');
const path = require('path');
const app = express();
const proxy = require('express-http-proxy');
const PORT = process.env.OPENSHIFT_NODEJS_PORT || 8080;
const API_PROXY_URL = process.env.APIURL
app.use(express.static(path.join(__dirname)));
app.use('/api', proxy(API_PROXY_URL));
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(PORT, () => {
console.log(`Server Started on port ${PORT}`);
console.log(`Proxy in use of ${API_PROXY_URL}`);
});
I have a generic api function which is making the calls using axios:
export function apiCall(method, path, data) {
return new Promise((resolve, reject) => {
return axios[method.toLowerCase()](path, data)
.then(res => {
return resolve(res.data);
})
.catch(err => {
return reject(err.response.data.error);
});
});
}
For example, my when I try and sign in it is trying to do a post call to <<REACTURL>>/api/auth/signin when I want it to send to <<APIURL>>/api/auth/signin.
I feel I'm missing something really obvious.
I couldn't get this to work as I wanted to ended up declaring the full URL in the API request to get it working. Not pretty, but does the job:
export function apiCall(method, path, data) {
let url = <<APIURL>> + path
return new Promise((resolve, reject) => {
return axios[method.toLowerCase()](url, data)
.then(res => {
return resolve(res.data);
})
.catch(err => {
return reject(err.response.data.error);
});
});
}