Skip to content

Commit

Permalink
Fix multer file size error handling using express error handler, incr…
Browse files Browse the repository at this point in the history
…ease max file size to 10MB, fix bug where uploads would not show up on home page and clarify README.md
  • Loading branch information
Sandermoen committed Jul 11, 2020
1 parent 10a8044 commit 915a660
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 67 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
> Install npm dependencies using npm install
```shell
$ npm install
$ npm install && cd client && npm install
```

> Set up a MongoDB database either locally or provision a free database with <a href='https://www.mongodb.com/cloud/atlas'>`MongoDB Atlas`</a>
Expand Down
11 changes: 9 additions & 2 deletions client/src/components/NewPost/NewPostForm/NewPostForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
selectCurrentUser,
} from '../../../redux/user/userSelectors';
import { showAlert } from '../../../redux/alert/alertActions';
import { addPost } from '../../../redux/feed/feedActions';

import { createPost } from '../../../services/postService';

Expand All @@ -25,6 +26,7 @@ const NewPostForm = ({
hide,
back,
showAlert,
addPost,
}) => {
const [caption, setCaption] = useState('');
const [loading, setLoading] = useState(false);
Expand All @@ -40,10 +42,14 @@ const NewPostForm = ({
previewImage.filterName && formData.set('filter', previewImage.filterName);
try {
setLoading(true);
await createPost(formData, token);
const post = await createPost(formData, token);
setLoading(false);
hide();
history.push('/');
if (history.location.pathname === '/') {
addPost(post);
} else {
history.push('/');
}
} catch (err) {
setLoading(false);
showAlert(err.message || 'Could not share post.', () =>
Expand Down Expand Up @@ -114,6 +120,7 @@ const mapStateToProps = createStructuredSelector({

const mapDispatchToProps = (dispatch) => ({
showAlert: (text, onClick) => dispatch(showAlert(text, onClick)),
addPost: (post) => dispatch(addPost(post)),
});

export default connect(mapStateToProps, mapDispatchToProps)(NewPostForm);
4 changes: 3 additions & 1 deletion client/src/services/postService.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,17 @@ export const votePost = async (postId, authToken) => {
* @function createPost
* @param {object} formData Multipart form data about the image being uploaded
* @param {string} authToken The user's auth token
* @returns {object} The created post
*/
export const createPost = async (formData, authToken) => {
try {
await axios.post('/api/post', formData, {
const post = await axios.post('/api/post', formData, {
headers: {
authorization: authToken,
'Content-Type': 'multipart/form-data',
},
});
return post.data;
} catch (err) {
throw new Error(err.response.data.error);
}
Expand Down
8 changes: 6 additions & 2 deletions controllers/postController.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ const filters = require('../utils/filters');
module.exports.createPost = async (req, res, next) => {
const user = res.locals.user;
const { caption, filter: filterName } = req.body;
let crop = req.body.crop;
let post = undefined;
const filterObject = filters.find((filter) => filter.name === filterName);
const hashtags = [];
Expand Down Expand Up @@ -66,7 +65,12 @@ module.exports.createPost = async (req, res, next) => {
});
await post.save();
await postVote.save();
res.status(201).send(response);
res.status(201).send({
...post.toObject(),
postVotes: [],
comments: [],
author: { avatar: user.avatar, username: user.username },
});
} catch (err) {
next(err);
}
Expand Down
48 changes: 29 additions & 19 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,6 @@ app.use(bodyParser.json());
app.set('trust proxy', 1);
app.use('/api', apiRouter);

app.use((err, req, res, next) => {
if (!err.statusCode) {
err.statusCode = 500;
console.log(err);
}
console.log(err.message);
res.status(err.statusCode).send({
error:
err.statusCode >= 500
? 'An unexpected error ocurred, please try again later.'
: err.message,
});
});

if (process.env.NODE_ENV === 'production') {
app.use(compression());
app.use(express.static(path.join(__dirname, 'client/build')));
Expand All @@ -62,6 +48,26 @@ if (process.env.NODE_ENV === 'production') {
}
})();

app.use((err, req, res, next) => {
console.log(err.message);
if (!err.statusCode) {
err.statusCode = 500;
}
if (err.name === 'MulterError') {
if (err.message === 'File too large') {
return res
.status(400)
.send({ error: 'Your file exceeds the limit of 10MB.' });
}
}
res.status(err.statusCode).send({
error:
err.statusCode >= 500
? 'An unexpected error ocurred, please try again later.'
: err.message,
});
});

const expressServer = app.listen(PORT, () => {
console.log(`Backend listening on port ${PORT}`);
});
Expand All @@ -74,12 +80,16 @@ console.log('Socket.io listening for connections');
io.use((socket, next) => {
const token = socket.handshake.query.token;
if (token) {
const user = jwt.decode(token, process.env.JWT_SECRET);
if (!user) {
return next(new Error('Not authorized.'));
try {
const user = jwt.decode(token, process.env.JWT_SECRET);
if (!user) {
return next(new Error('Not authorized.'));
}
socket.user = user;
return next();
} catch (err) {
next(err);
}
socket.user = user;
return next();
} else {
return next(new Error('Not authorized.'));
}
Expand Down
39 changes: 22 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"helmet": "^3.21.2",
"jwt-simple": "^0.5.6",
"linkifyjs": "^2.1.9",
"mongoose": "^5.9.1",
"mongoose": "^5.9.23",
"multer": "^1.4.2",
"nodemailer": "^6.4.6",
"socket.io": "^2.3.0",
Expand Down
26 changes: 2 additions & 24 deletions routes/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const postRouter = express.Router();
const multer = require('multer');
const upload = multer({
dest: 'temp/',
limits: { fileSize: 5 * 1024 * 1024 },
limits: { fileSize: 10 * 1024 * 1024 },
}).single('image');
const rateLimit = require('express-rate-limit');

Expand All @@ -24,29 +24,7 @@ const postLimiter = rateLimit({
max: 5,
});

postRouter.post(
'/',
postLimiter,
requireAuth,
(req, res, next) => {
upload(req, res, next, (err) => {
if (err) {
if (
err instanceof multer.MulterError &&
err.code === 'LIMIT_FILE_SIZE'
) {
return res.status(400).send({
error:
'The file you are trying to upload exceeds the upload limit of 5MB.',
});
}
return next(err);
}
next();
});
},
createPost
);
postRouter.post('/', postLimiter, requireAuth, upload, createPost);
postRouter.post('/:postId/vote', requireAuth, votePost);

postRouter.get('/suggested/:offset', requireAuth, retrieveSuggestedPosts);
Expand Down

0 comments on commit 915a660

Please sign in to comment.