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.
Related
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
Im building an express instance for the first time and ive run into an issue where everything works locally, but when deployed sending a post request to the route responds:
Failed to load resource: the server responded with a status of 405
(Not Allowed)
Ive included the relevant code below:
server/index.js
const express = require('express');
const bodyParser = require('body-parser')
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
const routes = require('./routes')(express)
require('./db')
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(process.env.PORT || 8080);
app.use('/', routes);
routes/index.js
var mongoose = require("mongoose");
const randomId = require('random-id');
const Submissions = require('../api/Submissions')
// routes/index.js
module.exports = (express) => {
// Create express Router
var router = express.Router();
// add routes
router.route('/submission')
.post((req, res) => {
let newSubmission = new Submissions(req.body);
newSubmission._id = randomId(17, 'aA0');
// Save the new model instance, passing a callback
newSubmission.save(function(err,response) {
if (err) {
console.log(err)
} else {
res.setHeader('Content-Type', 'application/json');
res.json({'success':true})
}
// saved!
})
});
return router;
}
client.js
let submission = {
name: this.state.newSubmission.name.trim(),
body: this.state.newSubmission.body.trim(),
email: this.state.newSubmission.email.trim(),
};
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(submission),
};
fetch("/submission", requestOptions)
.then((response) =>
response.json().then((data) => ({
data: data,
status: response.status,
}))
)
.then((res) => {
if (!res.data.success) {
notifier.warning('Failed to submit');
} else {
notifier.success('Submission successful');
}
});
I have a seperate frontend and backend, where all requests to http://frontend.com/api are proxied to the backend. However we allow image uploads to be 10mb max, which gets limited by the 1mb internal limit of express on all request bodies.
I have the following config:
const express = require('express');
const consola = require('consola');
const { Nuxt, Builder } = require('nuxt');
const helmet = require('helmet');
// Express
const app = express();
const host = process.env.HOST || '127.0.0.1';
const port = process.env.PORT || 8080;
app.set('port', port);
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js');
config.dev = !(process.env.NODE_ENV === 'production');
async function start() {
// Init Nuxt.js
const nuxt = new Nuxt(config);
if (config.dev) {
const builder = new Builder(nuxt);
await builder.build();
}
// NOTE: Only in production mode
if (!config.dev) {
// Helmet default security + Referrer + Features
app.use(helmet());
}
// Proxy /api to proper backend
app.use('/api', proxy(process.env.API_ENDPOINT || 'http://localhost:3000'));
// Give nuxt middleware to express
app.use(nuxt.render);
// Listen the server
app.listen(port, host);
consola.ready({
message: `Server listening on http://${host}:${port}`,
badge: true,
});
}
start();
I have tried adding body-parser, until I found out this only works for non multipart/form type of requests. Considering that this isn't an express backend, but only used to serve SSR (with nuxt), I have no idea how to get this to work with something like multer or busboy.
Can this be done without having to setup nginx as a reverse proxy?
Express itself doesn't impose any limits on body size, because it doesn't process the request body at all.
However, some middleware do impose a limit, like body-parser and express-http-proxy, which is what you're using.
To increase the limit to 10MB:
app.use('/api', proxy(process.env.API_ENDPOINT || 'http://localhost:3000', {
limit: '10mb'
));
The way mine works is I define my api base url in a config file which I reference in an api/init.js file. This file is added to plugins in nuxt.config.js. This is that file:
import axios from 'axios'
import {baseURL} from '~/config'
import cookies from 'js-cookie'
import {setAuthToken, resetAuthToken} from '~/utils/auth'
import { setUser, setCart } from '../utils/auth'
axios.defaults.baseURL = baseURL
const token = cookies.get('x-access-token')
const currentUser = cookies.get('userDetails')
const currentCart = cookies.get('userCart')
if (token) {
setAuthToken(token)
setUser(currentUser)
setCart(currentCart)
} else {
resetAuthToken()
}
The backend runs on it's own server which I launch with node index.js and it is the base url that my init.js looks for. The backend index.js looks like this:
const mysql = require('mysql')
const express = require('express')
const bodyParser = require('body-parser')
const config = require('./config')
const jwt = require('jsonwebtoken')
const bcrypt = require('bcrypt')
const multer = require('multer')
const auth = require('./auth')
const files = require('./files')
const create = require('./create')
const get = require('./get')
const delet = require('./delet')
const blogFiles = require('./blogFiles')
const db = mysql.createConnection(config.db)
const app = express()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
app.use((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, Content-Length, x-access-token, userDetails, userCart')
if (req.method === 'OPTIONS') {
res.sendStatus(200)
}
else {
next()
}
})
app.use((err, req, res, next) => {
if (err.code === 'LIMIT_FILE_TYPES') {
res.status(422).json({ error: 'Only images are allowed'})
return
}
if (err.code === 'LIMIT_FILE_SIZE') {
res.status(422).json({ error: `Too Large. Max filesize is ${MAX_SIZE/1000}kb` })
return
}
})
app.use('/auth', auth({db, express, bcrypt, jwt, jwtToken: config.jwtToken}))
app.use('/files', files({db, express, multer}))
app.use('/blogFiles', blogFiles({db, express, multer}))
app.use('/create', create({db, express}))
app.use('/get', get({db, express}))
app.use('/delet', delet({db, express}))
app.get('/test', (req, res) => {
db.query('select 1+1', (error, results) => {
if (error) {
return res.status(500).json({type: 'error', error})
}
res.json({type: 'success', message: 'Test OK', results})
})
})
app.listen(config.port)
console.log('App is running on port ' + config.port)
The files.js handles file uploads and as you can see index.js requires that. It is in there that I use multer to handle the upload limit and such. This is file.js
module.exports = ({db, express, multer }) => {
const routes = express.Router()
const fileFilter = function(req, file, cb) {
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
if (!allowedTypes.includes(file.mimetype)) {
const error = new Error('Wrong file type')
error.code = 'LIMIT_FILE_TYPES'
return cb(error, false)
}
cb(null, true)
}
const MAX_SIZE = 250000
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../frontend/assets/images')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
const upload = multer ({
storage: storage,
fileFilter,
limits: {
fileSize: MAX_SIZE
},
})
routes.post('/upload', upload.single('file'), (req, res) => {
res.json({ file: req.file })
})
return routes
}
As you can see I set the MAX_SIZE for my file uploads here so guess you can set any limit and as multer is handling it, it will over ride any limits set by express.
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 facing an issue while running the angular and nodejs app which I am trying to integrate with Neo4j app. The issues are the errors that I get-
POST http://localhost:7474/viewNodesStart 404 (Not Found)
and
EXCEPTION: Response with status: 404 Not Found for URL:
http://localhost:7474/viewNodesStart
Though this topic is repetitive in StackOverflow , I am still posting it because the following links suggestions didn't suit my issue.
Angular2 404 Not Found for URL: http://localhost/WebApi2/api/hero
EXCEPTION: Response with status: 404 Not Found for URL / Angular2
https://github.com/johnpapa/angular-tour-of-heroes/issues/94
Please check my code
app.component.ts
import { Component, OnInit } from '#angular/core';
import { Injectable } from '#angular/core';
import { ToasterService } from '../toaster.service';
import { FormGroup, FormControl, FormBuilder, Validators } from '#angular/forms';
import { Http, Response, Headers } from '#angular/http';
import { config } from '../config';
import { Subject } from 'rxjs';
import 'rxjs/add/operator/map';
import { map } from 'rxjs/operators';
import 'rxjs/Rx';
import { Observable } from 'rxjs';
// Statics
import 'rxjs/add/observable/throw';
#Component({
selector: 'app-neo4j-primary',
templateUrl: './neo4j-primary.component.html',
styleUrls: ['./neo4j-primary.component.css']
})
export class Neo4jPrimaryComponent implements OnInit {
constructor(private http: Http, private notify: ToasterService) { }
ngOnInit() {
this.viewNodesStart();
}
emptyObj;
info;
// ------------------------------- Nodes Entire Data --------------
viewNodesStart() {
console.log("INSIDE viewNodesStart()")
// Nodes Value
console.log("inside Nodes Value");
var data = localStorage.getItem('token');
console.log("data is=>",data);
var url = config.url;
var port = config.port;
this.http.post("http://"+url+":"+port+"/viewNodesStart",this.emptyObj)
.map(Response => Response.json())
.subscribe((res: Response) => {
console.log("XXXXXXXXXXXX Response on /viewNodesStart", res);
this.info = res;
console.log('success', this.info.statusCode);
if (this.info.statusCode == 200) {
this.notify.Success("Data added successfully");
} else {
this.notify.Error("Data is not inserted")
}
});
}
}
server.js
var express = require('express');
var cors = require('cors');
var bodyParser = require('body-parser');
const neo4j = require('neo4j-driver').v1;
var app = express();
var restify = require('restify');
var expressJwt = require('express-jwt');
var session = require('express-session');
var config = require('./config.json')
app.use(restify.plugins.bodyParser());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(bodyParser.json({
type: 'application/vnd.api+json'
}))
app.use(cors());
app.use(session({
secret: config.secret,
resave: false,
saveUninitialized: true
}));
//*****TM Server ******/
app.use('/viewNodesStart', require('./neo4jserver/tmserver'));
app.get('/', function(req, res) {
res.send('Welcome');
console.log("welcome in console");
});
// start server
var server = app.listen(7473, function() {
console.log('Server listening at http://' + server.address().address + ':' + server.address().port);
});
nodeserver.js
// Require Neo4j
var neo4j = require('neo4j-driver').v1;
var path = require('path');
var logger = require('morgan');
var bodyParser = require('body-parser');
var express = require('express');
var router = express.Router();
var app = express();
// Create Driver
const driver = new neo4j.driver("bolt://localhost:11001",neo4j.auth.basic("neo4j", "abc"));
// Run Cypher query
const cypher = 'MATCH (n) RETURN count(n) as count';
//View Engine
app.set('views', path.join(__dirname, 'views'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(express.static(path.join(__dirname, 'public')));
var session = driver.session();
app.post('/', function(req, res) {
console.log("INSIDE NODE JS CONTROLLER OF viewNodesStart");
console.log("BODY IS ", req.body);
var log = JSON.parse(req.body);
console.log(log);
session.run('MATCH (n) RETURN n LIMIT 25').then(function(result) {
result.records.forEach(function(record) {
console.log("record", record);
console.log("result = ", result)
console.log("record._fields[0].properties", record._fields[0].properties);
res.status(200).send({
statusCode: '200',
result: result
});
});
}).catch(function(err) {
console.log(err);
}).then(res=>{
console.log("res.records.length", res.records.length);
}
)
res.send('It Works');
res.send(result);
});
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === "OPTIONS")
res.send(200);
else
next();
}
console.log('Server started on port 11005');
module.exports = router;
module.exports = app;
I guess the problem is with the url you are passing to the http request. You are passing the path of the anuglar route and want to call the node api.
Change the url there to the nodeapi url. Then it will work.