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?
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 :D
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
Related
I have been following a tutorial on setting up REST APIs in Node, using Express for an app that accesses an existing MariaDB database. My version only needs to read data and I have the DB co-located with the Node application (same host).
My goal for this entry-level example is to just access the data, using static SQL, so I can see it rendered in the web page by the JSON pritifier.
[Next, I want to present the data in a table (EJS?). Later, when I can get that to work, I'll add form controls (React?) to let a user specify start and end date bounds for the SQL query. Finally I'll aim to render the data as a line graph (D3js).]
The tutorial runs the web server successfully (it returns 'OK' on the base URL), but when I go to URL/solarData it tries an async function to getMultiple rows from the DB, it responds:
Bind parameters must not contain undefined. To pass SQL NULL specify JS null TypeError: Bind parameters must not contain undefined. To pass SQL NULL specify JS null
at /SunnyData/solarViz/node_modules/mysql2/lib/connection.js:628:17
at Array.forEach (<anonymous>)
at Connection.execute (/SunnyData/solarViz/node_modules/mysql2/lib/connection.js:620:22)
at /SunnyData/solarViz/node_modules/mysql2/promise.js:120:11
at new Promise (<anonymous>)
at PromiseConnection.execute (/SunnyData/solarViz/node_modules/mysql2/promise.js:117:12)
at Object.query (/SunnyData/solarViz/services/db.js:6:40)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async Object.getMultiple (/SunnyData/solarViz/services/solarData.js:7:16)
at async /SunnyData/solarViz/routes/solarData.js:8:14
app.js:61
./app.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3800;
const solarDataRouter = require('./routes/solarData');
app.use(express.json());
app.use(
express.urlencoded({
extended: true,
})
);
app.get('/', (req, res) => {
res.json({'message': 'ok'});
})
app.use('/solarData', solarDataRouter);
/* Error handler middleware */
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
console.error(err.message, err.stack);
res.status(statusCode).json({'message': err.message});
return;
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
});
./routes/solarData.js
const express = require('express');
const router = express.Router();
const solarData = require('../services/solarData');
/* GET solar data. */
router.get('/', async function(req, res, next) {
try {
res.json(await solarData.getMultiple(req.query.page));
} catch (err) {
console.error(`Error while getting solar data `, err.message);
next(err);
}
});
module.exports = router;
./config.js
const env = process.env;
const config = {
db: {
host: env.SUNNY_HOST,
user: env.SUNNY_USER,
password: env.SUNNY_PW,
database: env.SUNNY_DB,
},
listPerPage: env.LIST_PER_PAGE,
};
module.exports = config;
./services/solarData.js
const db = require('./db');
const helper = require('../helper');
const config = require('../config');
async function getMultiple(page = 1){
const offset = helper.getOffset(page, config.listPerPage);
const rows = await db.query(
`SELECT * FROM DTP LIMIT ?,?`, [offset, config.listPerPage]
);
const data = helper.emptyOrRows(rows);
const meta = {page};
return {
data,
meta
}
}
module.exports.getMultiple = getMultiple;
./services/db.js
const mysql = require('mysql2/promise');
const config = require('../config');
async function query(sql, params) {
const connection = await mysql.createConnection(config.db);
const [results, ] = await connection.execute(sql, params);
return results;
}
module.exports = {
query
}
I've left out the ./helper.js
Everything runs fine until I direct the webpage to /solarData. At that point I get the Debug Console (vscode) mentioned up-front
Searching seems to point at a mysql2 shortcoming/bug but not at a practical solution
If you respond, please describe the 'bind' mechanism, as I'm not sure what's going on.
Hope I've put enough info in. Please ask if I need to add anything else.
The error says
Bind parameters must not contain undefined.
It means that in the file ./services/solarData.js on the line
const rows = await db.query(
`SELECT * FROM DTP LIMIT ?,?`, [offset, config.listPerPage]
);
Some of the 2 variables is undefined, you need to check offset and config.listPerPage to be defined.
Just use
console.log('offset: ' + offset)
console.log('listPerPage: ' + config.listPerPage)
and you will find out what is undefined in your case
I have created a login module using node server (ejs engine) listening on port 3000. Upon successful login with that module, i want to redirect that to another node server listening on port 2011 (made using jade engine). the redirect is not working properly.
The working of login module is such that it put an axios post request with username and password on a live website and get a successcode in return. There is no registration required as the authentication is done by that live website.
Both the servers(3000 and 2011) are working fine but the redirect is not working
Can I route the other node app(2011) on the same server with "localhost:3000/welcome" domain?
'use strict'
const express=require("express");
const app=express();
const path=require("path");
const port=process.env.PORT || 3000
const pubdir=path.join(__dirname,"/public");
const bodyParser = require('body-parser')
const axios=require("axios");
// const axiosCookieJarSupport = require('axios-cookiejar-support').default;
// const tough = require('tough-cookie');
// const https = require('https');
// const Cookie=require("request-cookies").Cookie;
// const http=require("http");
// axiosCookieJarSupport(axios);
// const request= require("request");
var urlencodedParser = bodyParser.urlencoded({ extended: false })
const offlineroute=require("./router")
app.set("view engine", "ejs");
app.use(express.static(pubdir))
app.get("/",(req,res)=>{
res.render("index");
})
const url uat="It's a valid url working fine"
const url_uat_auth="Another url working fine"
app.post("/login",urlencodedParser,(req,resp)=>{
const data = {
username:req.body.user_name,
password:req.body.user_pass,
captcha:"121212",
deviceID: null,
}
const apiData={
action: "ACCESSTOKEN",
username: data.username,
password: data.password,
}
axios.post(url_uat, data)
.then((res) => {
// console.log(`Status: ${res.status}`);
console.log('Body: ', res.data);
// console.log("headers",res.headers);
if(res.data.message=='auth')
{
console.log("Successfully logged in");
// app.use("/welcome",offlineroute);
resp.redirect("localhost:2011"); //Help me here.
(async ()=>{
try {
const response = await axios.get(url_uat_auth, apiData);
console.log(response.status);
console.log(response.headers);
} catch (error) {
console.log(error.response.body);
}
})();
}
else if(res.data.message==null && res.data.errorCode=='AUTH_9002')
{
console.log("Wrong username or password");
}
else if(res.data.message==null && res.data.errorCode=='SWEB_9000')
{
console.log("Invalid Captcha");
}
}).catch((err) => {
console.error(err);
});
})
app.listen(port,(req,res)=>{
console.log(`Listening on Port ${port}` );
});
Try to add the full protocol and port:
resp.redirect("http://localhost:2011");
I'm trying to connect from Nodejs to DialogFlow. I have completed all the steps to configure the user agent, the intent, etc. If I lunch with NODEMON the app, all its ok, but when I send a GET or POST request I get this error:
"UnhandledPromiseRejectionWarning: TypeError: sessionClient.projectAgentSessionPath" and more. But I think the most relevant mistake is this.
The code I used it's the same as the APi docs. I don't know why I get this error.
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const dialogflow = require('#google-cloud/dialogflow');
const uuid = require('uuid');
//const sendReq = require('./reqDialogFlow');
async function runSample(projectId = 'helpcenter-qwoj') {
// A unique identifier for the given session
const sessionId = uuid.v4();
// Create a new session
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);
console.log(sessionPath);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: 'hello',
// The language used by the client (en-US)
languageCode: 'it',
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
};
app.get('/', (req, res) => {
res.send({ "hello": "Daniele Asteggiante" })
});
app.post('/api/textAPIE', (req, res) => {
res.send({ "text": "CIAO" });
runSample();
});
app.use(bodyParser.json());
const PORT = process.env.PORT || 5000;
app.listen(PORT);
i had the same error.
i had installed
npm i dialogflow
instead of
npm install #google-cloud/dialogflow
I tried to change the Express Version version with an earlier version 4.17.0 instead 4.17.1.
Now it goes.
change "sessionClient.projectAgentSessionPath" -> "sessionClient.sessionPath"
Found this solution on github:https://github.com/googleapis/nodejs-dialogflow/issues/127
I've used cors for my express server, but I can't figure out why it's not working. Can anyone please help me with this issue?
Access to XMLHttpRequest at
'https://tic-tac-toe-server.now.sh/socket.io/?EIO=3&transport=polling&t=N6Z2b4X'
from origin 'http://localhost:8080' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource.
Client:
import io from 'socket.io-client';
const socket = io('https://tic-tac-toe-server.now.sh')
Here is my index.js
const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const cors = require('cors');
const router = require('./router');
const { addUser, removeUser, getUsers } = require('./users');
const { getMatch, addPlayer, destroyMatch } = require('./players');
const PORT = process.env.PORT || 5000;
const app = express();
const server = http.createServer(app);
const io = socketio(server);
app.use(router);
app.use(cors());
io.on('connection', function (socket) {
const id = socket.id;
let user_room = '';
/**
* User Joins to the global room
*/
socket.on('join', function ({ name, room, playing = false }) {
addUser({ id, name, room, playing }); // add user to users array
user_room = room;
socket.join(user_room);
socket.join(id);
socket.emit('user_joined', getUsers());
socket.broadcast.emit('user_joined', getUsers()); // emit event with modified users array
});
/**
* Match Started
*/
socket.on('player_joined', user => {
const match = getMatch();
addPlayer(user.match, user);
if(match.hasOwnProperty(user.match) && match[user.match].length === 2){
socket.emit('player_joined', match[user.match]);
socket.broadcast.to(user.match).emit('player_joined', match[user.match]);
}
});
socket.on('move', (data) => {
socket.emit('move', data);
socket.broadcast.to(data.match).emit('move', data);
});
socket.on('emote', (data) => {
socket.emit('emote_from', data);
socket.broadcast.to(data.match).emit('emote_to', data);
});
/**
* On user challenge
*/
socket.on('challenge', (socketId) => {
io.to(socketId).emit('accept', id);
});
socket.on('rejected', (socketId) => {
io.to(socketId).emit('rejected', id);
});
socket.on('accepted', data => {
io.to(data.opponent.id).emit('accepted', data);
socket.emit('accepted', data);
});
socket.on('player_left_match', match => {
socket.broadcast.to(match).emit('player_left_match');
});
socket.on('destroy_match', match => {
destroyMatch(match);
});
/**
* User Disconnect function
*/
socket.on('disconnect', () => {
socket.leave(user_room);
socket.leave(id);
removeUser(id); // remove user form users array
socket.emit('user_left', getUsers());
socket.broadcast.emit('user_left', getUsers()); // emit event with modified users
})
});
server.listen(PORT, () => console.log(`Server running on port ${PORT}`));
You can tell socket.io to only use the webSocket transport which is not subject to CORS by changing this:
const socket = io('https://tic-tac-toe-server.now.sh')
to this:
const socket = io('https://tic-tac-toe-server.now.sh', {transports: ['websocket']});
Some background. In its default configuration, socket.io starts every connection with multiple plain http requests. These plain http requests require server-side CORS support if the connection is cross-origin. But, socket.io can be configured to go straight to the webSocket transport (which is what is eventually ends up using anyway) and webSocket connections are not subject to CORS limitations.
The socket.io design to start with http polling was largely there because in the early days of webSocket support, not every browser supported it and not every server infrastructure supported it. But now-a-days, it is pretty widely supported.
So, telling socket.io to start with the webSocket transport from the beginning avoids many potential CORS issues.
We are now chasing a different issue and the error showing in the console at https://tic-tac-toe-vue.now.sh/ is coming from this code in webSocket.js.
try {
this.ws =
this.usingBrowserWebSocket && !this.isReactNative
? protocols
? new WebSocketImpl(uri, protocols)
: new WebSocketImpl(uri)
: new WebSocketImpl(uri, protocols, opts);
} catch (err) {
return this.emit('error', err);
}
It looks like something React related since there's a reference to isReactNative, but since your code is packaged and minimized, it's not very easy to do any debugging from here.
I ran into a problem and I feel that node-http-proxy is changing my target links. I got a few examples below.
I am using express as my server and using Metaweather API .
The problem is that I was able to get data from the endpoints below
https://www.metaweather.com/api/location/2487956/
https://www.metaweather.com/api/location/2487956/2013/4/30/
But when I try to call the API from https://www.metaweather.com/api/location/search/?lattlong=36.96,-122.02
It fails with status code 500 which I lead me thinking that node-http-proxy added some values after 122.02 as it was not closed with /
server.js
const express = require("express");
const next = require("next");
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
const httpProxy = require("http-proxy");
const proxyOptions = {
changeOrigin: true
};
const apiProxy = httpProxy.createProxyServer(proxyOptions);
const apiUrl =
"https://www.metaweather.com/api/location/search/?lattlong=36.96,-122.02";
/*
https://www.metaweather.com/api/location/search/?lattlong=36.96,-122.02 - failed with 500
https://www.metaweather.com/api/location/2487956/ - passed
https://www.metaweather.com/api/location/2487956/2013/4/30/ - passed
*/
app
.prepare()
.then(() => {
const server = express();
server.use("/api", (req, res) => {
console.log("Going to call this API " + apiUrl);
apiProxy.web(req, res, { target: apiUrl });
});
server.get("*", (req, res) => {
return handle(req, res);
});
server.listen(3000, err => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});
Thanks for looking into this question.
I have reproduced where this is happening in node-http-proxy.
In common.js there is a function called urlJoin which is appending the req.url to the end of the target url.
I'm not exactly sure what the intent is, but it's a start.
Here's my test:
const urlJoin = function() {
//
// We do not want to mess with the query string. All we want to touch is the path.
//
var args = Array.prototype.slice.call(arguments),
lastIndex = args.length - 1,
last = args[lastIndex],
lastSegs = last.split('?'),
retSegs;
args[lastIndex] = lastSegs.shift();
//
// Join all strings, but remove empty strings so we don't get extra slashes from
// joining e.g. ['', 'am']
//
retSegs = [
args.filter(Boolean).join('/')
.replace(/\/+/g, '/')
.replace('http:/', 'http://')
.replace('https:/', 'https://')
];
// Only join the query string if it exists so we don't have trailing a '?'
// on every request
// Handle case where there could be multiple ? in the URL.
retSegs.push.apply(retSegs, lastSegs);
return retSegs.join('?')
};
let path = urlJoin('/api/location/search/?lattlong=36.96,-122.02', '/');
console.log(path);
// /api/location/search/?lattlong=36.96,-122.02/