Home » vue » Why Node.js can't process the request from Vue.js?

Why Node.js can't process the request from Vue.js?

Posted by: admin November 26, 2021 Leave a comment

Questions:

I have strange error and don’t know why Node.js don’t see url address and always return me 404.

In Vue.js application I make post request with axios package when user click the button. As you can see from the code I send name of the file in the body of request and user token in the header. I check and both values are not empty.

getFile (fileName) {
    axios.post('/csv', {file_name: fileName}, {headers: {'Authorization': this.token}}).then(response => {
        console.log(response)
        this.showAlert('File successfully downloaded.', 'is-success', 'is-top')
    }).catch((error) => {
        console.log(error)
        this.showAlert('An error occurred while downloading the file.', 'is-danger', 'is-bottom')
    })
}

ERROR:

Error: Request failed with status code 404
    at FtD3.t.exports (createError.js:16)
    at t.exports (settle.js:18)
    at XMLHttpRequest.f.(:3010/anonymous function) (http://localhost:3010/static/js/vendor.1dc24385e2ad03071ff8.js:1312:88758)

All requests from browser goes to HTTP server in Node.js (Express.js). In my case csv.js file should process the request. I don’t understand in what part of the project problem. By the way other urls works correctly.

server/bin/www.js:

/**
 * Module dependencies.
 */
const app = require('../../app')
const debug = require('debug')('slot:http-server')
const http = require('http')

/**
 * Get port from environment and store in Express.js.
 */
let port = normalizePort(process.env.PORT || '3010')
app.set('port', port)

/**
 * Create HTTP server.
 */
const server = http.createServer(app)

/**
 * Listen on provided port, on all network interfaces.
 */
server.listen(port)
server.on('error', onError)
server.on('listening', onListening)

/**
 * Normalize a port into a number, string, or false.
 */
function normalizePort (val) {
  const port = parseInt(val, 10)
  if (isNaN(port)) {
    return val
  }
  if (port >= 0) {
    return port
  }
  return false
}

/**
 * Event listener for HTTP server "error" event.
 */
function onError (error) {
  if (error.syscall !== 'listen') {
    throw error
  }
  const bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port
  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges')
      process.exit(1)
      break
    case 'EADDRINUSE':
      console.error(bind + ' is already in use')
      process.exit(1)
      break
    default:
      throw error
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */
function onListening () {
  const address = server.address()
  const bind = typeof address === 'string' ? 'pipe ' + address : 'port ' + address.port
  debug('Listening on ' + bind)
}

app.js:

const express = require('express');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors');
const path = require('path');

const locationsRouter = require('./server/routes/locations');
const csvRouter = require('./server/routes/csv');

const app = express();

app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'dist')));

app.use('/api/locations', locationsRouter);
app.use('/csv', csvRouter);

module.exports = app;

server/routes/csv.js:

const express = require('express')
const router = express.Router()

const fs = require('fs')
const path = require('path')

let Client = require('ssh2-sftp-client')
let sftp = new Client()

const config = require('../config')

router.post('/', (req, res) => {
  // Set the variable with the name of the file.
  const fileName = req.body.file_name

  // Path to file in remote SFTP server.
  const remotePath = '/reports/' + fileName

  // Local directory where the downloaded file will be placed
  const localePath = path.join(process.env.HOME || process.env.USERPROFILE, 'downloads/' + fileName)

  // Connect to remote SFTP server.
  sftp.connect(config.sftpServer, 'on').then(() => {
    // Download file from remote SFTP server to local machine of the user.
    sftp.fastGet(remotePath, localePath, {}).then(() => {
      res.setHeader('Content-disposition', 'attachment; filename=' + fileName)
      res.sendFile(localePath)
      fs.unlink(localePath)
    }).catch((error) => {
      console.log(error)
    })
  }).catch((error) => {
    console.log(error)
  })
})

module.exports = router

What can you guys advice?

Answers:

In vue, you are doing a post request to /csv, but in your app.js you are defining the /csv route as GET, that is your problem 😀

UPDATE

If you want this to work with the animation download like chrome
Take a look at this link
https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743