Wednesday, April 4, 2018

Express: unable to access route from browser due to accept:application/javascript header missing

Leave a Comment

I'm new to express. I have a Vue application running on express. I have some API routes that I'm able to access using axios through the browser. To access those routes using postman I have to have the header:

accept: application/javascript 

for it to return the result of the actual API. If I don't use this header, I get the generated index.html from webpack. I need to reuse one of these routes to return excel/pdf, based on a parameter and have it accessible via a link on the page.

Here's my server.js - based on https://github.com/southerncross/vue-express-dev-boilerplate

import express from 'express'  import path from 'path'  import favicon from 'serve-favicon'  import logger from 'morgan'  import cookieParser from 'cookie-parser'  import bodyParser from 'body-parser'  import webpack from 'webpack'    const argon2 = require('argon2');  const passport = require('passport')  const LocalStrategy = require ('passport-local')  const session = require('express-session')      import history from 'connect-history-api-fallback'    // Formal(Prod) environment, the following two modules do not need to be introduced  import webpackDevMiddleware from 'webpack-dev-middleware'  import webpackHotMiddleware from 'webpack-hot-middleware'    import config from '../../build/webpack.dev.conf'    const app = express()  app.set('trust proxy', true)    app.set("view engine", "pug")  app.set('views', path.join(__dirname, 'views'))    app.use ('/', require('./routes'))      app.use(session({  	secret: process.env.SESSION_SECRET || 'secretsauce',  	resave: false,  	saveUninitialized: true  }))      app.use(history())  app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))  app.use(logger('dev'))  app.use(bodyParser.json())  app.use(bodyParser.urlencoded({  	extended: false  }))  app.use(cookieParser())  app.use(express.static(path.join(__dirname, 'public')))    const compiler = webpack(config)    app.use(webpackDevMiddleware(compiler, {  	publicPath: config.output.publicPath,  	stats: {  		colors: true  	}  }))    app.use(webpackHotMiddleware(compiler))        ////////// PASSPORT ///////////////////////  app.use (passport.initialize ());  app.use (passport.session ());    async function authenticateUser (username, password) {  //...  		  }    passport.use (  	new	LocalStrategy (async (username, password, done) => {  		const user = await authenticateUser (username, password)  		if (!user) {  			return done (null, false, {  				message: 'Username and password combination is wrong',  			});  		}    		delete user.password;  		return done (null, user)  	})  );    // Serialize user in session  passport.serializeUser ((user, done) => {  	done (null, user);  });    passport.deserializeUser (function(user, done) {  	if(user === undefined || !user || Object.keys(user).length === 0)  		return done(null, false)  	else  		done (null, user);  });    //////////// passport end ///////////////      app.set("view engine", "pug")  app.use(express.static(path.join(__dirname, 'views')))  app.get('/', function (req, res) {  	res.sendFile('./views/index.html')  })  app.get('/success', function (req, res) {  	res.render('./views/success')  })        app.use ('/api', require('./api'))      // catch 404 and forward to error handler  app.use(function (req, res, next) {  	var err = new Error('Not Found')  	err.status = 404  	next(err)  })    app.use(function (err, req, res) {  	res.status(err.status || 500)  	res.send(err.message)  })          let server = app.listen(80)    export default app

And here's a bit of api.js

const {Router} = require ('express')  const router = Router()    router.get('/whome', function(req, res){  	logger.info('whome', req.user)  	return res.json(req.user)  })      router.get ('/hello', auth.isAuthenticated, async (req, res) => {  	res.json ({text:'hello'})  })    module.exports = router

I can call http://localhost/api/hello from postman with the accept:application/javascript header and I get:

{     "text": "hello" } 

as expected. But if I call the same URL from the browser (and it's not sending that header), I get the created bundle index.html. How can I access these routes from the browser?

1 Answers

Answers 1

You have two options.

First one, try to add this in your server:

app.options('*', cors())

before to: app.set("view engine", "pug")

If that doesnt work, try to install this addon in your Google Chrome browser to test.

Allow-Control-Allow-Origin: *

And enable it. (The icon should be green instead of red).

Why this happens? The request that's being made is called a preflight request. Preflight requests are made by the browser, as CORS is a browser security restriction only - This is why it works in Postman, which is, of course, not a browser.

Reference: Preflight request

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment