So I'm running it on port 8080. Port forwarding has been set up and it is working.
Every time I type in my no-ip domain, I get the response on the screen but when I'm making a request from my website, it logs the request on the Raspberry, yet, there is no response visible in the Chrome developer tools.
I also get this error message: POST "name of the api" net::ERR_EMPTY_RESPONSE
What could cause that? My routes worked perfectly when I was running my api locally.
module.exports = function(app) {
app.get('/', requireAuth, function(req, res) {
res.send({ message: 'OMG, You made it, you deserve a drink!' });
});
That's how my react app looks like:
const ROOT_URL = *"name of the api"/*;
.
.
.
export function fetchMessage() {
return function(dispatch) {
axios.get(ROOT_URL, {
headers: { authorization: localStorage.getItem('token') }
})
.then(response => {
dispatch({
type: FETCH_MESSAGE,
payload: response.data.message
});
});
}
};
Is it a typical problem of the Node.js, Express, React or maybe it's on the Raspi? Thanks a lot!
Possibly a CORS issue, since the problem only happens when trying to consume the API from the browser. A possible solution is to use the cors package in your Express application:
const express = require('express');
const cors = require('cors');
...
const app = express();
app.use(cors());
...
NOTE: this enables all CORS requests.
Related
I am a beginner in server side programming. Trying to write code that will allow me to get data from state variable, send it to my backend and use nodemailer service to send it to an email adress. My frontend is as follows :
const handleSubmit = async () => {
try {
await axios.post(
"http://localhost:2525/send_mail",
{
state
}
);
} catch (error) {
console.log(error);
}
};
state gets sent to backend :
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const nodemailer = require('nodemailer');
require('dotenv').config();
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.options('',cors());
app.get('/', (req, res) => {
res.send('Server is running');
});
app.post("/send_mail", cors(), async (req, res) => {
let { state } = req.body;
const transport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'adress#mail.com',
pass:'password'
}
});
await transport.sendMail({
from: '<myemail.#example.com>',
to: "reciever#example.com",
subject: "test email",
html: `<div><p>${state.Message}</p></div>`
});
});
app.listen(process.env.PORT || 2525, () => { console.log("Server is running"); });
If it matters, state is an object that gets filled from form data, it looks something like :
const data = {
FirstName: "",
LastName: "",
Message:"",
};
When i visit port 2525, server is indeed running with the message i gave it. But when i try to submit my form with "handleSubmit", i get the following console error:
*>
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:2525/send_mail. (Reason: CORS request did not succeed). Status code: (null).*
And it crashes the server
As you can see i am already using cors middleware to try to handle it.
I tried adding a proxy to the package.json file, as : "proxy": "http://localhost:2525", ( i did not change anything else when i did that, i don't know if that is the correct way). This did not solve anything, but at least the server did not crash any more. Instead, the POST request gets a 404:
*
POSThttp://localhost:2525/send_mail Referrer Policystrict-origin-when-cross-origin*
I tried running it in Chrome, same problem. I tried everything i could read on stackoverfrlow google or chat gpt, really that is cors-related. Even checked if port is maybe taken by something else in windows, checked that in cmd. Im at my wits end really
I'm learning Express and I face an issue which I can't understand.
When I route to /addPerson I expect to log the name: 'Mike', age: 30 to the console. Instead I got nothing logged to the console. What's wrong in my code?
here's the server.js code
const Express = require('express'),
app = Express(),
PORT = process.env.PORT || 5000,
parser = require('body-parser'),
data = []
// initialize the main project folder
app.use(Express.static('public'))
// running the server
app.listen(PORT, () => {
console.log(`Server is running at port ${PORT}`);
})
// include body parser to handle POST requests
app.use(parser.urlencoded({extended: false}))
app.use(parser.json())
// setup CORS
const cors = require('cors')
app.use(cors())
// GET request
app.get('/', (req, res) => {
res.send('<h1>Home Page</h1>')
})
app.get('/addPerson', (req, res) => {
res.send('<h1>Hello Hany</h1>')
})
// POST request
app.post('/addPerson', (req, res) => {
data.push(req.body)
console.log(data);
})
and here is the client side app.js code
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);
}
}
postData('/addPerson', {name: 'Mike', age: 30});
this the files structure
Alright, I've taken a look at your code and this is what I've noticed. Within your server.js file you have this code block:
app.get('/addPerson', (req, res) => {
res.send('<h1>Hello Hany</h1>')
})
That is sending back a static H1 tag when the user creates a get request to localhost:5000/addPerson. Then, directly below that you have your post route but you're never fully accessing that from anywhere (I looked through all your app.js code to double check).
Instead, I have changed your code to return a static html file with a button that allows you to call this function (just as an example so you can see that your routes do in fact work). This isn't the cleanest solution to your problem but I just wanted to make sure you see where the problem lies as I've been in your shoes before when I first started working with express. You can take a look at the CodeSandbox I setup below to replicate your issue and take a look through all the code to get an understanding.
To properly solve your issue using the app.js file you would have to serve the javscript file as your "frontend". Personally I'm a big fan of React so I usually serve my frontend with React, while my backend is express. You can also very easily serve this file using NodeJS in a similar fashion that you are with your "backend". If you were to take the React approach you would be able to modify this code:
app.get("/addPerson", (req, res) => {
res.sendFile(path.resolve(__dirname, "public", "index.html"));
});
To find the frontend section you desire using React (I can recommend react-router if you require multiple routes but I don't want to overwhelm you with too much information yet) and complete the same function. If you have any questions feel free to reach out and let me know! Hopefully this helps!
I'm an adjunct professor teaching a React/Mongoose course online. Last term many students started encountering problems either with CORS or 404 errors popping up on what was otherwise good code. I've been fighting for a solution for several weeks now.
First of all, when launching the app in Chrome 93.0.4577.63, all I get is a CORS error without any other helpful information that I can decypher: "Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://reactjs.org/link/crossorigin-error for more information."
I am able to get further in Edge.
In case it makes any difference, the server.js file is in the root of the application, but the app code is located in a folder called "client". This is a portion of the /context/userProvider.js page in that client folder that is calling an axios function. The key portion of the code is the signup function().
import React, {useState} from "react";
import axios from "axios";
export const UserContext = React.createContext()
const userAxios = axios.create()
userAxios.interceptors.request.use(config => {
const token = localStorage.getItem("token")
config.headers.Authorization = `Bearer ${token}`
return config
})
export default function UserProvider(props){
const initState ={
user: JSON.parse(localStorage.getItem("user")) || {},
token: localStorage.getItem("token") || "",
comments: []
}
const [userState, setUserState] = useState(initState)
function signup(credentials){
axios.post("/auth/signup", credentials)
.then(res => {
const {user, token} = res.data
localStorage.setItem("token", token)
localStorage.setItem("user", JSON.stringify(user))
setUserState(prevUserState => ({
...prevUserState,
user,
token
}))
})
.catch(err => console.log(err))
}
I have the following line of code in the package.json file that sets the proxy to the port on which react is running:
"proxy": "http://localhost:9000"
Here is code from the server.js file that launches the mongoose server on port 9000:
app.use('/api', expressJwt({secret: process.env.SECRET, algorithms: ['RS256']}));
app.use('/auth', require("./routes/authRouter.js"));
app.use('/api/issue', require("./routes/issueRouter"));
app.use('/api/comment', require("./routes/commentRouter"));
app.use('/api/user', require("./routes/userRouter.js"))
app.use((err, req, res, next) => {
console.log(err)
if(err.name === "Unauthorized Error"){
res.status(err.status)
}
return res.send({errMsg: err.message})
});
app.listen(9000, () => {
console.log("The App is listening on port 9000")
});
When the user provides the user credentials on a fully functioning sign-up page, the credentials are successfully passed to the signup function, as shown from a console.log(credentials), but then I get the 404 error returned from the .catch portion of the signup function.
{username: 'csanders', password: 'chumisyum', firstName: 'chumbucket', lastName: 'sanders', phoneNumber: '1231231234'}
UserProvider.js:35 Error: Request failed with status code 404
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:62)
When I run the same operation through Postman on port 3000, I get the following error.
<pre>Cannot POST /auth/signup</pre>
But when I run it through Postman on port 9000, it appears to work fine:
Can anyone give me any insight on either how to clear the CORS error in Chrome or how to get the 404 error in Edge to go away? I'm getting desperate!
I believe your proxy inside package.json file should point to your server, not to your react application itself.
"proxy": "http://www.yourapi.com"
Note: You should add the previous command in package.json within react application NOT the server and you need to restart your react app to take effect.
Using CORS in Express:
Also, you may enable CORS on the server side by adding CORS middleware to your server object.
1- install cors by npm or yarn:
npm install cors
2- append CORS to your server object:
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
You can check the documentation for other cases like restricting access to specific origins:
http://expressjs.com/en/resources/middleware/cors.html
i seriously need help with this:
i built my first node js server, here:
var express = require('express'),
app = express(),
https = require('https');
port = process.env.PORT || 443,
mongoose = require('mongoose'),
Task = require('./api/models/myCarModel'),
bodyParser = require('body-parser');
fs = require("fs");
const options = {
key: fs.readFileSync('./static/HttpsFile/privatekey.pem').toString(),
cert: fs.readFileSync('./static/HttpsFile/certificate.pem').toString(),
};
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/Tododb');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var routes = require('./api/routes/myCarRoutes'); //importing route
routes(app); //register the route
https.createServer(options, app).listen(port);
console.log(options.key)
console.log('RESTful API server started on: ' + port);
and here's my simple react-native app home:
import React, { useState } from 'react';
import { useEffect } from 'react';
import { Button, StyleSheet, Text, TextInput, View } from 'react-native';
const Home = () => {
const [text, setText] = useState('');
useEffect(()=> {
debugger
fetch('https://192.168.1.8:443/cars', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}})
//axios.get("https://192.168.1.8:3000/cars")
.then((res:any) => {
debugger;
}, (err:any) => {
console.log(err)
debugger;
})
}, [])
return(...etc...)
now:
when I first used postman to test the API I got an error regarding the use of self-signed certificates ( which I'm using through OpneSSL ). I kindly asked Postman to accept the idea, and everything went on fine.
This is not the case with react-native:
I'm using expo, testing my app on my android phone and when I debug the API call I get the following error in the error-then: "TypeError: Network request failed".
I don't want to dirty solve the problem by making Android accept HTTP protocol.
Ty everyone
So you are running the app on your phone? Your phone does not have access to the server you are running on your computer. 'https://192.168.1.8:443/cars' is only accessible if you try to connect to it on the same device (it could be a simulator running on your computer). But still this may not work if you use an internal device. In that case you can access it trough http://10.0.2.2:433 (this worked for me).
Bonus point: Https does not work on local computer. Since it cant verify the request. When testing localy use "http".
To start the Bot Framework webchat client, I need to 'get' a token from a restify server running in Azure. The server fetches the token (using my secret) from https://webchat.botframework.com/api/tokens. The last part works fine. The first part didn't. I did not manage to get the webchat client to accept the response from the restify server. Offline (localhost) works fine. When the server is running online (Node in Azure) I get:
Access to fetch at 'https://mybot.azurewebsites.net/api/token' from origin 'https://mydomainname.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In the dev tool of chrome I can see that with restify server running on local host, I get an access-control-allow-origin and an access-control-expose-header. When running on Node (in Azure) I only get access-control-expose-header.
What did I already try (without a good result):
Implement cors middleware for restify server
Use Express in stead of restify
add headers manually to the response: res.send(token, { 'Access-Control-Allow-Origin': '*' })
specify the domain name in the (trusted) origins list of Cors middelware
[the solution] add the domain name running the calling javascript in the list with approved origins in the azure app service running the restify service.
My current code (with the Cors middleware)
Restify server
const fetch = require('node-fetch');
const restify = require('restify');
const path = require('path');
const corsMiddleware = require('restify-cors-middleware');
const cors = corsMiddleware({
origins: ['*']
});
// Create HTTP server and Cors
let server = restify.createServer();
server.use(cors.actual);
server.listen(process.env.port || process.env.PORT || 3978, function() {
console.log(`\n${ server.name } listening to ${ server.url }.`);
console.log(`\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator.`);
});
// Listen for bot requests.
server.post('/api/messages', (req, res) => {
adapter.processActivity(req, res, async (context) => {
await bot.run(context);
});
});
// Listen for token requests.
server.get('/api/token',
async function(req, res) {
const result = await fetch('https://webchat.botframework.com/api/tokens', {
method: 'GET',
headers: {
Authorization: `Bearer ${ process.env.directLineSecret }`
}
});
const token = await result.json();
console.log(token);
res.send(token);
});
The webchat client
In this code snippet, the client is talking to a server running on local host. This works. As soon as we talk to a server hosted on Azure, it doesn't work anymore (due to cors it seems)
(async function () {
const res = await fetch('http://localhost:3978/api/token', { method: 'GET' });
const webChatToken = await res.json();
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token: webChatToken })
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
Someone any thoughts on how to fix this?
Had me searching for a day and trying lots of options.
The solution was in Azure App Service (Node) CORS origins won't work no matter where I add them
You have to add the calling domain in the list of approved origins in the CORS menu of the appservice running your restify service.
Not sure if this makes sense, but it helped.