I cannot access the supplied url param in my delete endpoint and i have no idea why. GET, POST and PUT works just fine.
const express = require("express");
const app = express();
app.use(express.json());
const courses = [
{id: 1, name: 'course1'},
{id: 2, name: 'course2'},
{id: 3, name: 'course3'},
];
app.delete('/api/courses/:id', (res, req) => {
console.log(req.params.id);
});
I do a DELETE in Postman supplying the url "localhost:5000/api/courses/1" and i get the response:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>TypeError: Cannot read property 'id' of undefined
<br> at app.delete (C:\Users\Ove\WebstormProjects\Vidley\index.js:84:28)
<br> at Layer.handle [as handle_request] (C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\layer.js:95:5)
<br> at next (C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\route.js:137:13)
<br> at Route.dispatch (C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\route.js:112:3)
<br> at Layer.handle [as handle_request] (C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\layer.js:95:5)
<br> at C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\index.js:281:22
<br> at param (C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\index.js:354:14)
<br> at param (C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\index.js:365:14)
<br> at Function.process_params (C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\index.js:410:3)
<br> at next (C:\Users\Ove\WebstormProjects\Vidley\node_modules\express\lib\router\index.js:275:10)
</pre>
</body>
</html>
Could anyone please explain to me what is going on here? Only the DELETE endpoint acts like this, all others are fine
Express passes your handler (req, res), not (res, req), so your req is actually res and doesn't have a .params field.
Related
I wrote this small Express server to get data from an HTML form and query OpenWeatherMap with that data:
const { OpenWeatherAPI } = require("openweather-api-node");
const express = require("express");
const bodyParser = require("body-parser");
const path = require("path");
const app = express();
const PORT = process.env.port || 3000;
app.use(bodyParser.urlencoded({ extended: true }));
app.listen(PORT, () => console.log(`Server listening on port ${PORT}.`));
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "/public/views/index.html"));
});
app.post("/weather/public", (req, res) => {
let city = Number(req.body.city);
let units = (req.body.units || "").trim().toUpperCase();
if (!["IMPERIAL, METRIC, STANDARD"].includes(units)) {
$("h1").innerText =
"Please input Imperial, Metric or Standard for the units.";
return;
}
let weather = new OpenWeatherAPI({
key: MY_OPENWEATHERMAP_API_KEY,
locationName: city,
units: units,
});
weather.getCurrent().then((data) => {
res.send(
`<p>Current temperature in ${city} is: ${data.weather.temp.cur}</p>`
);
});
});
The HTML itself is very simplistic:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Weather query</title>
</head>
<body>
<h1>Input a city and your units!</h1>
<form action="/weather/public" method="post">
<input name="city" placeholder="Your city here" type="text" />
<input
name="units"
placeholder="Units of Measurement (imperial, metric, standard)"
type="text"
/>
<button name="submit" type="submit">Calculate!</button>
</form>
</body>
<script
crossorigin="anonymous"
integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ="
src="https://code.jquery.com/jquery-3.6.1.min.js"
></script>
<script charset="utf-8" src="../../app.js"></script>
</html>
When running the server and inputting a few items in the form, I get:
ReferenceError: $ is not defined
at C:\Users\jason\code\Web-Development\weather\app.js:19:5
at Layer.handle [as handle_request] (C:\Users\jason\code\Web-Development\weather\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\jason\code\Web-Development\weather\node_modules\express\lib\router\route.js:144:13)
at Route.dispatch (C:\Users\jason\code\Web-Development\weather\node_modules\express\lib\router\route.js:114:3)
at Layer.handle [as handle_request] (C:\Users\jason\code\Web-Development\weather\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\jason\code\Web-Development\weather\node_modules\express\lib\router\index.js:284:15
at Function.process_params (C:\Users\jason\code\Web-Development\weather\node_modules\express\lib\router\index.js:346:12)
at next (C:\Users\jason\code\Web-Development\weather\node_modules\express\lib\router\index.js:280:10)
at C:\Users\jason\code\Web-Development\weather\node_modules\body-parser\lib\read.js:137:5
at AsyncResource.runInAsyncScope (node:async_hooks:204:9)
Line 19 is the only location in the .js file where jquery is used:
$("h1").innerText = "Please input Imperial, Metric or Standard for the units.";
I changed the location of the <script> tag for jquery to be inside the <head> block but this did not help. I'm wondering whether it is even possible for me to use jquery inside Express' handlers or whether this is impossible and I should instead send an error HTML file as a response.
Answered by Pointy in the commments; effectively I can't be mixing up calls to client-side jquery from server-side Express code.
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
var baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
var explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
I'm trying to route a Cloud Foundry app (that uses Loopback 3) to a context path host.domain.com/this-path.
At first, just using cf create-route and cf map-route didn't work. I'd get a 404 error, so I changed the root.js in my Loopback app to include this-path.
'use strict';
module.exports = function(server) {
// Install a `/` route that returns server status
var router = server.loopback.Router();
router.get('/this-path', server.loopback.status());
server.use(router);
};
It was able to get the loopback status at host.domain.com/this-path, but API calls/additional paths won't work I just get errors like this. So then I tried changing the Loopback config.json's restApiRoot to include the path as well but that also gave me errors like this:
"error": {
"statusCode": 404,
"name": "Error",
"message": "Cannot POST /this-path/api/make-something",
"status": 404,
"stack": "Cannot POST /this-path/api/make-something\n at raiseUrlNotFoundError (/home/vcap/app/node_modules/loopback/server/middleware/url-not-found.js:21:17)\n at Layer.handle [as handle_request] (/home/vcap/app/node_modules/express/lib/router/layer.js:95:5)\n at trim_prefix (/home/vcap/app/node_modules/express/lib/router/index.js:317:13)\n at /home/vcap/app/node_modules/express/lib/router/index.js:284:7\n at Function.process_params (/home/vcap/app/node_modules/express/lib/router/index.js:335:12)\n at next (/home/vcap/app/node_modules/express/lib/router/index.js:275:10)\n at /home/vcap/app/node_modules/express/lib/router/index.js:635:15\n at next (/home/vcap/app/node_modules/express/lib/router/index.js:260:14)\n at Function.handle (/home/vcap/app/node_modules/express/lib/router/index.js:174:3)\n at router (/home/vcap/app/node_modules/express/lib/router/index.js:47:12)\n at Layer.handle [as handle_request] (/home/vcap/app/node_modules/express/lib/router/layer.js:95:5)\n at trim_prefix (/home/vcap/app/node_modules/express/lib/router/index.js:317:13)\n at /home/vcap/app/node_modules/express/lib/router/index.js:284:7\n at Function.process_params (/home/vcap/app/node_modules/express/lib/router/index.js:335:12)\n at next (/home/vcap/app/node_modules/express/lib/router/index.js:275:10)\n at nosniff (/home/vcap/app/node_modules/dont-sniff-mimetype/index.js:4:5)"
}
}
So now I'm wondering Where does url in var baseUrl = app.get('url').replace(/\/$/, ''); come from and can I change it so my app listens on host.domain.com/this-path?
I'm trying to use firebase for the first time with a web-applicaiton, but I get this error about .child is not a function. Can anyone please show the right way to connect to the firebase database collection, if what i am doing is wrong.
If I prefer to use mongoDb instead of firebase, how should I implement my post method in this case?
This is the error I get upon posting the form on the site.
TypeError: fbRef.child is not a function
at C:\Users\WorkoutApp_v1\routes\workouts.js:32:23
at Layer.handle [as handle_request] (C:\Users\WorkoutApp_v1\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\WorkoutApp_v1\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\WorkoutApp_v1\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\WorkoutApp_v1\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\WorkoutApp_v1\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\WorkoutApp_v1\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\WorkoutApp_v1\node_modules\express\lib\router\index.js:275:10)
at Function.handle (C:\Users\WorkoutApp_v1\node_modules\express\lib\router\index.js:174:3)
at router (C:\Users\WorkoutApp_v1\node_modules\express\lib\router\index.js:47:12)
This is the post method in my router file.
var express = require('express');
var router = express.Router();
const Firebase = require('firebase');
const fbRef = 'https://console.firebase.google.com/project/workout-7f912/database/firestore /data~2Fexercise~2F2zCvky1fWQcD14tTCq8B';
router.post('/add', function(req,res,next) {
var workout = {
name: req.body.Name,
discription: req.body.Discription,
set: req.body.Set,
RepsTime: req.body.RepsTime
}
// console.log(workout);
// return;
var dbRef = fbRef.child('workouts');
dbRef.push().set(workout);
req.flash('success_msg', 'Workout saved');
res.redirect('/workouts');
});
fbRef is a string and does not contain a method called child. You need to first connect to firebase database then you can do the following:
const fbRef = firebase.database().ref();
var dbRef = fbRef.child('workouts');
For more information check the following:
https://firebase.google.com/docs/database/web/start
Writing a webapp that uses async/await but got stuck where the line var r1 = await fetch(url).then((r) => r.text()) appears to be handing forever. My web server listening on port 80 didn't even receive the request.
const fetch = require ('fetch-node')
const express = require('express');
const app = express();
var savedResolve;
app.listen(8079, '127.0.0.1', function() {
console.log('listening on 8079')
})
app.get('/*', async function (req, res) {
console.log(req.path)
res.setHeader('Content-Type', 'text/html');
await task()
res.send('Done')
})
async function task() {
console.log("starting..")
var url = "http://localhost/prod/te.php";
var r1 = await fetch(url).then((r) => r.text())
console.log(r1)
return "done"
}
Any ideas? Thanks in advance!
Update1
Thanks to suggestion by #deryck, add try and catch around the line of fetch call, got the following error instead
TypeError: Cannot read property 'render' of undefined
at module.exports (/Users/jsmith/learn/node/node_modules/hooks-node/hooks-node.js:8:11)
at module.exports (/Users/jsmith/learn/node/node_modules/fetch-node/fetch-node.js:17:1)
at task (/Users/jsmith/learn/node/te4b.js:22:18)
at /Users/jsmith/learn/node/te4b.js:13:8
at Layer.handle [as handle_request] (/Users/jsmith/learn/node/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/jsmith/learn/node/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/Users/jsmith/learn/node/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/jsmith/learn/node/node_modules/express/lib/router/layer.js:95:5)
at /Users/jsmith/learn/node/node_modules/express/lib/router/index.js:281:22
at param (/Users/jsmith/learn/node/node_modules/express/lib/router/index.js:354:14)
node-fetch and fetch-node are two differnt libraries.
And based on the shown code node-fetch is the library that should be used.
I am implementing this in Nodejs to upload files (photos, mp3, pdf) to amazon web services s3. Currently am trying to upload an mp3 file but I keep getting tis error: "TypeError: Cannot read property 'path' of undefined". I am using the Multipart middlemware.
var fs = require('fs');
//S3FS instance
var S3FS = require('s3fs')
//multiparty middleware (to upload our file)----> S3FS will read it's object and stream it to AWS
//nmp install connect-multiparty
var multiparty = require('connect-multiparty'),
multipartyMiddleware = multiparty();
var express = require('express');
var route = express.Router();
module.exports = route;
route.use(multipartyMiddleware);
//create new filesystem
var s3fsImpl = new S3FS('unasbeatz', {
accessKeyId: 'xxxxxxx',
secretAccessKey: 'xxxxx'
});
//create bucket ----> unasbeatz
s3fsImpl.create();
route.post('/', function (req, resp) {
//get the file from our request object (from multiparty object, it sets the request object)
var file = req.files.file;
//create new readstream
var stream = fs.createReadStream(file.path);
//write to AWS using stream
return s3fsImpl.writeFile(file.originalFileName, stream).then(function () {
fs.unlink(file, function (err) {
if (err)
console.error(err);
})
//else we write uploaded
console.log('uploaded');
})
})
route.get('/', function (req, resp) {
resp.json({ SecretData: 'abcde' })
});
var stream: grabs direct part of every uploaded file. But I don't know why the error comes up
error:
TypeError: Cannot read property 'path' of undefined
at /Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/app/routes/mp3_route.js:34:42
at Layer.handle [as handle_request] (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/layer.js:95:5)
at /Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:277:22
at Function.process_params (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:330:12)
at next (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:271:10)
at multipart (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/connect-multiparty/index.js:50:53)
at Layer.handle [as handle_request] (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:312:13)
at /Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:330:12)
at next (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:271:10)
at Function.handle (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:176:3)
at router (/Users/AzeezOlusegunOdumosu/Desktop/unasbeatz/node_modules/express/lib/router/index.js:46:12)
Use busboy to receive files in the route.
What I finally implemented was to updload my files in AWS and save their urls in MongoDB,I then reuest for these urls in my web application to show these files in the browser