I'm trying to allow access only from my frontend and to restrict all others access from direct URL on API/postman and other things. I saw some examples here but I couldn't solve this thing.. This is my currently app.js:
const fs = require('fs');
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const companiesRoutes = require('./routes/companies-routes');
const usersRoutes = require('./routes/users-routes');
const adsRoutes = require('./routes/ads-routes');
const HttpError = require('./models/http-error');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
app.use(bodyParser.json());
const cors = require('cors');
const corsOptions ={
origin:'http://localhost:3000',
credentials:true,
optionSuccessStatus:200
}
app.use('/uploads/images', express.static(path.join('uploads', 'images')));
app.use('/uploads/videos', express.static(path.join('uploads', 'videos')));
app.use('/uploads/videos/thumb', express.static(path.join('uploads', 'videos/thumb')));
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE, PUT');
next();
});
app.use('/api/companies', companiesRoutes);
app.use('/api/users', usersRoutes);
app.use('/api/ads', adsRoutes);
app.use(cors(corsOptions))
app.use((req, res, next) => {
const error = new HttpError('Could not find this route.', 404);
throw error;
});
app.use((error, req, res, next) => {
if (req.file) {
fs.unlink(req.file.path, err => {
console.log(err);
});
}
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500);
res.json({ message: error.message || 'An unknown error occurred!' });
});
and last mongoose.connect etc.
Maybe I did something wrong here but I cant realize where's the problem in this code. I got this example about CORS here from other topic but it didn't solve my problem.
Try this:
const fs = require('fs');
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const companiesRoutes = require('./routes/companies-routes');
const usersRoutes = require('./routes/users-routes');
const adsRoutes = require('./routes/ads-routes');
const HttpError = require('./models/http-error');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
app.use(bodyParser.json());
const cors = require('cors');
var corsOptions = {
origin: 'http://localhost:3000',
optionsSuccessStatus: 200, // For legacy browser support
methods: "GET, PUT" // add per need
}
app.use(cors(corsOptions));
app.use('/uploads/images', express.static(path.join('uploads', 'images')));
app.use('/uploads/videos', express.static(path.join('uploads', 'videos')));
app.use('/uploads/videos/thumb', express.static(path.join('uploads', 'videos/thumb')));
app.use('/api/companies', companiesRoutes);
app.use('/api/users', usersRoutes);
app.use('/api/ads', adsRoutes);
app.use((req, res, next) => {
const error = new HttpError('Could not find this route.', 404);
throw error;
});
app.use((error, req, res, next) => {
if (req.file) {
fs.unlink(req.file.path, err => {
console.log(err);
});
}
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500);
res.json({ message: error.message || 'An unknown error occurred!' });
});
Note: Visit this link Handling CORS with Node.js if you interest a more better way to work with CORS
Related
this is the front end :
function App() {
const [Todo1, setTodos] = useState([]);
useEffect(() => {
axios
.get("http://localhost:5000/api/todos")
.then((res) => {
console.log(res.data);
setTodos(res.data);
})
.catch((err) => {
console.log(err);
});
}, []);
return (
<div className="App">
<h1>My Todo List</h1>
<Task Todor={Todo1} />
</div>
);
}
and this is the routes in the backend :
const express = require('express');
const router = express.Router();
const Todo = require('../models/todo');
router.get('/todos', (req, res, next) => {
Todo.find()
.then(data => res.json(data))
.catch(next)
});
and this is from backend server :
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const routes = require('./routes/api');
const path = require('path');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
//connect to the database
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true })
.then(() => console.log(`Database connected successfully`))
.catch(err => console.log(err));
//since mongoose promise is depreciated, we overide it with node's promise
mongoose.Promise = global.Promise;
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(bodyParser.json());
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:5000',
changeOrigin: true,
})
);
};
app.use('/api', routes);
app.use((err, req, res, next) => {
console.log(err);
next();
});
app.listen(port, () => {
console.log(`Server running on port ${port}`)
});
and this is the errors iam getting :
1- AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
2- GET http://localhost:5000/api/todos net::ERR_CONNECTION_REFUSED
I tried everything , and nothing seems to work !!
I have created a simple server in node js to take the request from a react app.
But for the GET method there is no CORS error but whenever I do post, it gives me an error.
For the POST method to work, I have implemented in index.js file of the actions folder and it should hit the url from the server.js file.
index.js
import axios from 'axios';
export const GET_NAVBAR = "GET_NAVBAR";
export const LOGIN = "LOGIN";
export const BASE_API_URL = "http://localhost:3030";
export const GUEST_API_URL = "https://XXX.XXX.XXX.X:5443/wcs/resources/store/1";
export const getNavbar = () => {
return axios.get(BASE_API_URL + '/topCategory').then(res => {
return {
type: GET_NAVBAR,
payload: res.data.express.catalogGroupView
};
});
};
export const login = () => {
return axios.post(GUEST_API_URL + '/guestidentity', {}).then(res => {
console.log(res);
return {
type: LOGIN,
payload: {}
}
}).catch(e => {
console.log(e);
return {
type: LOGIN,
payload: {}
}
});
};
server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const Client = require('node-rest-client').Client;//import it here
const app = express();
const helmet = require('helmet');
const morgan = require('morgan');
// enhance your app security with Helmet
app.use(helmet());
// use bodyParser to parse application/json content-type
app.use(bodyParser.json());
app.use(cors());
// log HTTP requests
app.use(morgan('combined'));
app.post('/guestidentity', (req, res) => {
var client = new Client();
// direct way
client.post("https://XXX.XXX.XXX.X:5443/wcs/resources/store/1/guestidentity", (data, response) => {
res.send({express: data});
});
});
const port = 3030;
app.listen(port, () => console.log(`Server running on port ${port}`));
I don't know where my code is getting wrong. Can anybody please help me to troubleshoot this issue. I would be grateful if someone could provide an insight or guide me a little. Thanks
For my part I used
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
It will accept from any * sources, you might want to change that later
In your server.js , add the following middleware.
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3030/');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
};
app.use(allowCrossDomain);
I am stuck with a problem from last 3 hours, I was trying to upload file and other post data to the server side, I am using angular for frontend part and node for server side.
This is my component.ts code
save(data) {
console.log(data);
const files: Array<File> = this.filesToUpload;
console.log(files);
for(let i = 0; i < files.length; i++){
this.formData.append("image[]", files[i], files[i]['name']);
}
//trying to send some dummy entry but no luck
this.formData.append('title','dasdasdas');
// console.log(this.formData.getAll('image'));
// console.log('form data variable : '+
this.formData.toString());
// console.log(this.formData.getAll('image[]'));
this.restApi.addRecipe(this.formData).subscribe(res =>
{
console.log(res);
});
This is my angular service code:
addRecipe(data){
console.log(this.baseUrl);
const headers = new Headers({});
let options = new RequestOptions({ headers });
return this.http.post(this.baseUrl+'addRecipe',data,options).map(res=>res.json());
}
This is my server.js code:
const express = require('express');
const mongoose = require('mongoose');
const admin = require('./routes/admin');
const path = require('path');
const app = express();
const config = require('./config/config');
const bodyParser = require('body-parser');
const cors = require('cors');
mongoose.Promise = global.Promise;
mongoose.connect(config.database, (err) => {
if (err) {
console.log(err);
} else {
console.log('connected')
}
})
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'client/dist')));
app.use(cors());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'DELETE, PUT');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
//admin route
app.use('/admin', admin);
app.listen(3000, (err) => {
if (err) console.log("err");
console.log("port started");
})
This is the controller code where I have written the logic of inserting:
module.exports.addRecipe = (req, res) => {
const body = req.body
console.log(body);
return;
...
}
whenever I console.log(body), I am getting a empty object {}, from the angular side I have tried changing the content type but nothing seems to be working, I am new to node and angular and I searched a lot about this problem but no solution seems to be working.
I tried about 10 different options but I cant get my POST request start working instead i have options request that is pending and never completes
server.js
var express = require('express');
var path = require('path');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
app.use(cors());
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Accept');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
} else {
next();
}
};
app.use(allowCrossDomain);
app.options('*', cors());
app.use(require('./routes/order-templates.js'));
app.use(require('./routes/statuses.js'));
app.use(require('./routes/fields.js'));
app.use(require('./routes/users.js'));
app.use(require('./routes/groups.js'));
app.use(require('./routes/upload.js'));
app.use(require('./routes/feedback.js'));
app.use(require('./routes/order.js'));
app.use(express.static('public'));
var mongoDB = 'mongodb://localhost/ior';
mongoose.connect(mongoDB, {
useMongoClient: true
});
app.get('*', function (request, response) {
response.sendFile(path.resolve(__dirname, 'public', 'index.html'))
})
app.listen(3000, function () {
console.log('Fired at ' + Date());
});
users.js
var express = require('express');
var router = express.Router();
var User = require('../model/user.js');
var bodyParser = require('body-parser');
var app = express();
var cors = require('cors')
var corsOptions = {
origin: 'http://188.225.82.166:3000/',
optionsSuccessStatus: 200
}
app.use(cors())
app.use(bodyParser.json());
app.options('/users/auth/', cors(corsOptions))
app.post('/users/auth/', cors(), function (req, res, next) {
User.findOne({"mail": req.body.mail, "password": req.body.password}, function (err, user) {
if (err) throw err;
if (user == undefined) {
res.send({"result": "error" })
res.sendStatus(200)
} else {
res.send({"result": "ok", "_id": user._id, "type": user.type })
}
});
})
module.exports = app
If I do
app.use(cors());
app.use(function(req, res, next) {
console.log('After CORS ' + req.method + ' ' + req.url);
next();
});
in server.js I get
After CORS GET /
After CORS GET /bundle.js
After CORS GET /bootstrap.css.map
After CORS GET /favicon.ico
And nothing prints in console after post requests is triggered.
Also worth mentioning the fact, that the problem exists only when I deploy to server with ubuntu. Locally on mac os machine everything is fine
You should use cors before bodyParser and allow it for PUT/DELETE also.
// Add cors
app.use(cors());
app.options('*', cors()); // enable pre-flight
app.use(bodyParser.json());
It may be helpful for others like me:
In the beginning I thougth it is the server side problem, but then the reason of cors error became my frontend. I was sending requests to localhost:3000/api instead of http://localhost:3000/api
That's it
For others like me scratching head for 2hrs trying to fix the POST cors issue, please also double check the options of your POST request.
For me it was a small typo of header: {...} instead of header(s): {...} in the POST options, the express server configured using cors allowing all origins responded with "Access-Control-Allow-Origin" restricted error.
Try this. In you user.js file use router.post instead of app.post.
router.post('/users/auth/', cors(), function (req, res, next) {
User.findOne({"mail": req.body.mail, "password": req.body.password}, function (err, user) {
if (err) throw err;
if (user == undefined) {
res.send({"result": "error" })
res.sendStatus(200)
} else {
res.send({"result": "ok", "_id": user._id, "type": user.type })
}
});
})
Then export router module
module.exports = router;
Also i would suggest to use bodyparser in server.js file. So you don't need to use it in every file.
After applying "cors" middleware. You should append "http://" before "localhost:". in URL
axios.get("http://localhost:8080/api/getData")
.then(function (response) {
this.items= response.data;
}).catch(function (error) {
console.log(error)
});
Get rid of the trailing slash in origin.
I'm I'm stuck in post request while I'm developing upload images in quill editor.
I have no idea what I have to do to fix this issue.
When I try to send data using post request, then 404 error occur.
routes/img.js - UPDATED
var ImageFile = require('../models/imageFiles');
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'img/') // Set directory
},
filename: function (req, file, cb) {
cb(null, file.name) // Set file name
}
});
var img = multer({ storage: storage });
router.post('/upload', img.single('imgfile'), (req, res, next) => {
var imageFile = new ImageFile({
name: req.body.name,
type: req.body.type,
size: req.body.size,
content: req.body.content
});
imageFile.save((err, result) => {
if (err) {
return res.status(500).json({
title: 'An error occured',
error: err
});
}
res.status(201).json({
message: 'User created',
obj: result
});
});
});
module.exports = router;
app.js
const express = require('express');
var bodyParser = require('body-parser');
const port = process.env.PORT || 3000;
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var appRoutes = require('./routes/app');
var userRoutes = require('./routes/user');
var imgRoutes = require('./routes/img');
var app = express();
// Start
app.use(express.static(path.join(__dirname, '../awesome-drill/dist')));
app.use(logger('dev'));
app.use(bodyParser.json({ limit: '10mb' }));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-Width, Content-Type, Accept');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE, OPTIONS');
next();
});
app.use('/user', userRoutes);
app.use('/img', imgRoutes);
app.use('/', appRoutes);
app.use(express.static('routes'));
// It's for routing SPA
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../awesome-drill/dist/index.html'));
});
app.listen(port, () => {
console.log(`Server is up on port ${port}`);
});
frontside service (angular4)
import { Injectable } from '#angular/core';
import {Http, Headers, Response} from '#angular/http';
#Injectable()
export class FileService {
public userId = localStorage.getItem('userId');
constructor(private http: Http) { }
imgUpload(obj) {
const body = JSON.stringify(obj);
const headers = new Headers({
'Content-Type': 'application/json'
});
return this.http.post('img/upload', body, {
headers: headers
})
.map((response: Response) => response.json());
}
}
Thanks to you, I found my mistake and I added it. However, 404 error still occur.
It's my folder structure.
You aren't exporting your router. Add the following to the end of your routes/img.js file.
module.exports = router;
The way you have it now, there is no default export, so when you require('./routes/img') you're importing nothing. If you were to console.log(imgRoutes) in app.js it would probably return undefined.