Axios get request keeps hitting 404 - javascript

This is the get request:
this.props.userId contains the userId.
componentDidMount() {
axios.get('/api/auth/booked/' + this.props.userId)
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
This is the routes on my backend:
router.get('/booked:id', UserController.bookedClasses);
It's something to do with the '/booked:id'
Result:
GET http://localhost:3000/api/auth/booked/5bdb18071c8fb30d31969aef 404 (Not Found)
Nice and simple but for some odd reason, I can't get a response, I have all my system working apart from this route, can anyone spot anything that shouldn't be there?
Any feedback would be appreciated to help me and others!
This is my routes folder which holds all my routes:
const express = require('express');
const router = express.Router();
const UserController = require('../controllers/auth');
router.post('', UserController.createUser);
router.post('/login', UserController.login);
router.post('/bookclass', UserController.bookClass);
router.get('/:id', UserController.getUser);
router.get('/booked:id', UserController.bookedClasses);
module.exports = router;

Router params must be specified in the path of the route. Example:
'/some/route/:param'
or with multiple params:
'/some/route/:param/:anotherParam'
In your example:
router.get('/booked:id', UserController.bookedClasses);
should be (check the extra / in the path):
router.get('/booked/:id', UserController.bookedClasses);

Related

detect a request using NodeJS without express or accessing the request object outside an express middleware [duplicate]

This question already has answers here:
Access current req object everywhere in Node.js Express
(2 answers)
Closed 8 months ago.
This post was edited and submitted for review 8 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I have the following lines of code:
const express = require('express');
const app = express()
// ... defining the routes, app.get('/api/users', (req, res, next)=>{ }) ...etc
app.listen(3000, ()=> console.log('Listening on port 3000...'))
module.exports = app
I want to be able to read the request object outside an express middleware.
I have another file called mongoose_models.js, inside that file, I don't have the access to the express middleware arguments (req, res, next).
And the only option I have for reading the request body from that file is to import the app and somehow read the request Object.
NodeJs is event-driven, so there must be a way somehow to do so, for instance, inside the file mongoose_models.js I would have maybe something like this code:
// mongoose_models.js
// ... some code
const app = require('../app.js')
app.on('request', (req)=>{
// here I have the request
})
or maybe if express supports:
// mongoose_models.js
// ... some code
const { req } = require('express')
console.log(req.body) // ? maybe something like that ?
or maybe if express supports too:
// mongoose_models.js
// ... some code
const app = require('../app.js')
app.onRequest((req, res) => {
// here I have the access to the request object
})
Is there a way to reach the request object without having to be inside an express middleware in NodeJS?
edit:
Some of you asked me to provide the source code, unfortunately, I wanted to provide a stackblitz or code sandbox instance, but I didn't know how to set up the connections to the database.
Anyway, the following is the file structure of the sample project:
app.js file (full code):
const express = require('express')
const app = express()
const mongoose = require('mongoose')
const RoomModel = require('./mongoose_models')
app.use((req, res, next) => {
// this middleware is the "protect" middleware, it validates a JWT (JSON web token), decodes it, and then stores the user it finds to the req object:
// .... etc some code
// decode the JWT .. some code
// find the user in the DB const userDoc = await UserModel.findOne({ _id: decodedJWT.id )})
const userDoc = {
id: 'abc-123-edf-cds-123-321-qu5-eu4-dc9-182',
name: 'Murat',
// and some other fields ... etc
}
req.$loggedInUser = userDoc
})
app.get('/rooms', async(req, res, next) => {
const docs = await RoomModel.find({})
res.status(200).json({
message: 'here are all the rooms',
results: docs.length,
data: docs,
})
})
app.post('/rooms', async(req, res, next) => {
const doc = await RoomModel.create(req.body)
res.status(201).json({
message: 'the new room which got created:',
data: doc,
})
})
// connecting to the database:
mongoose.connect(
'mongodb+srv://USERNAME:PASSWORD#YOUR_CLUSTER.mongodb.net/?retryWrites=true&w=majority'
)
// starting the HTTP service:
app.listen(3000, () => console.log('app listening on port 3000...'))
mongoose_models.js file (full code):
const mongoose = require('mongoose')
const roomSchema = new mongoose.Schema({
name: String,
by: mongoose.Schema.ObjectId,
})
roomSchema.pre('save', function(next) {
// Here I want to make the by field be the req.$loggedInUser.id but I can't because I have no way to read the request object
const doc = this
// doc.by = req.$loggedInUser.id // < ----- 👈👈👈 HERE, I can't reach the req object
next()
})
const RoomModel = mongoose.model('Room', roomSchema, 'rooms')
module.exports = RoomModel
NodeJS is event driven, so there must be a way somehow to do so, for
instance, inside the file mongoose_models.js I would have maybe
something like this code:
// mongoose_models.js
// ... some code
const app = require('../app.js')
app.on('request', (req)=>{
// here I have the request
})
This approach is, essentially, middleware. So write is as middleware.
const myMiddleware = (req, res, next) => {
// here you have the request
next(); // go to next middleware
}
module.exports = myMiddleware
Attaching something to listen for requests is done with use (for non-method specific functions) and post, get, etc. There is no on method or onRequest method.
// mongoose_models.js
// ... some code
const { req } = require('express')
console.log(req.body) // ? maybe something like that ?
The request object doesn't exist until the client makes a request to the server.
You get a new request object each time a request is made.
The server might be handling multiple requests at the same time.
So no, you can't do anything like that.
Is there a way to reach the request object without having to be inside an express middleware in NodeJS?
No.

collection.find({}) doesnt work after many tries

I am building an api with express and mongoose and im usingdb.collection(collection).find({}) expecting that i get all of my docs back (3 test docs in total) as seen from tutorials. It doesnt give me any errors when im executing a req from postman and that confuses me as im geting nothing, not even an empty object or array as a response. I have tried different examples, from different tutorials but nothing works. Is the syntax wrong?
import express from 'express'
import './connection.js'
const router = express.Router
const db = mongoose.connection;
const dtb = db.useDb('main').collection('products')
router.get('/true', async(req, res) => {
try {
const products = await dtb.find({})
res.send(products).status(200)
} catch (err) {
console.log(err)
res.sendStatus(500)
}
})
So, after lookig again and again at my code I realized that the route /true was taken as a param by express as i have another route for app.get('/:_id', getItem).
After changing the route to /all/true parsing the docs into an array and after some debugging, my getAll function looks like this and finally works :
export const getAll = app.get('/all/true', async(req, res) => {
const products = await dtb.find({}).toArray().catch(console.error())
res.send(products)
})

Node/Express - use API JSON response to (server-side) render the app

Preamble: I'm new to web dev so maybe this might be a very basic question for you vets.
I'm using MVC architecture pattern for this basic app. I've models (MongoDB), views (Express Handlebars), and controllers (functions that take in req, res, next and returns promises (.then > JSON is returned, .catch > error is returned). I'll be routing the paths reqs to their corresponding api endpoints in the controllers.
This makes sense (right?) when I'm purely working on API calls where JSON is the res. However, I also want to call these api endpoints > get their res.json > and use that to render my HTML using Handlebars. What is the best way to accomplish this? I can create same controllers and instead of resp being JSON, I can do render ("html view", res.json). But that seems like I'm repeating same code again just to change what to do with the response (return JSON or Render the JSON).
Hope I'm making sense, if not, do let me know. Please advise.
p.s. try to ELI5 things for me. (:
Edit:
//Model Example
const Schema = require('mongoose').Schema;
const testSchema = new Schema({
testText: { type: String, required: true },
});
const Test = mongoose.model('Test', testSchema);
module.exports = Test;
//Controller Example
const model = require('../models');
module.exports = {
getAll: function(req, res, next) {
model.Test.find(req.query)
.then((testItems) => {
!testItems.length
? res.status(404).json({ message: 'No Test Item Found' })
: res.status(200).json(testItems);
})
.catch((err) => next(err));
},
};
//Route Example
const router = require('express').Router(),
controller = require('../controllers');
router.get('/', controller.getAll);
module.exports = router;
I want the endpoints to return JSON and somehow manage whether to render (if the req comes from a browser) or stay with JSON (if called from Postman or an API web URL for example) without repeating the code. I'm trying to not create two endpoitns with 99% of the code being the same, the only difference being .then > res.status(200).json(testItems); vs .then > res.status(200).render('testPage', { testItems}).
For postman you could check the existence of postman-token in req.headers, then you could render accordingly, something like this:
req.headers['postman-token'] ? res.json({ /* json */ }) : render('view', {/ * json */});
If you want to go with checking postman token then you can use similar to method1.
if you want to check with query params in this case you can get json response or html even from browser for future use also and is not dependent on postman then use similar to method2 of the following example.
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
const port = 5000
app.get('/method1', (req, res) => {
const isJSONResp = req.headers['postman-token']
const resp = { status: "hello" }
if (isJSONResp) {
res.json(resp)
} else {
res.render('some.html', resp)
}
})
app.get('/method2', (req, res) => {
const params = req.params
const resp = { status: "hello" }
if (params.resp === 'json') {
res.json(resp)
} else {
res.render('some.html', resp)
}
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))

params looking for id being fired on another route when it shouldn't

I'm new to mongoose so I apologise for incorrect uses of terminology.
I have a routes file as detailed below
const express = require('express');
const router = express.Router();
const passport = require('passport');
const controller = require('./clubController');
const authGuard = passport.authenticate('jwt', { session: false });
const verifyUser = require('./clubController').verifyUser;
const isSiteAdmin = require('./clubController').isSiteAdmin;
router.param('id', controller.params);
router.route('/')
.post(authGuard, controller.newClub)
.get(controller.allPublicClubs);
router.route('/:id')
.put(authGuard, verifyUser(), controller.editClub)
.get(controller.getClub);
router.route('/private')
.get(controller.allPrivateClubs);
module.exports = router;
controller.params
exports.params = function(req, res, next, id) {
Club.findById(id)
.populate('creator teams', '-password -email -role')
.exec()
.then(function(club) {
if (!club) {
return res.status(404).send({ msg: 'No Club exists with that ID' });
} else {
req.club = club;
next();
}
}, function(err) {
// error handling
next(err);
});
};
controller.params is being fired when I make a get request to /private. To my understanding, the params middleware I have setup should only be fired when a called route is using an id parameter.
The value for the id argument in controller.params is set as private which is the route.
The error I receive is detailed below
CastError: Cast to ObjectId failed for value "private" at path "_id" for model "club"
This was working fine yesterday, no idea what changed that it now does not work.
I solved the issue by moving
router.route('/:id')
.put(authGuard, verifyUser(), controller.editClub)
.get(controller.getClub);
To the bottom of all the routes. Was strange as I had the same order before and it worked fine

How to use Browser history in react router with koa

In the express, we can just use following codes to deal with the request. The server side will send index.html when the request that isn't handled by router.
app.get('*', function (request, response){
response.sendFile(path.resolve(__dirname, '../public', 'index.html'))
})
But in koa, the following code don't work. When the request isn't handled by koa-router, it will return 404 instead of index.html.
var send = require('koa-send')
var serve = require('koa-static')
var router = require('koa-router')
var koa = require('koa')
var app = koa();
app.use(serve(__dirname+'/../public'));
app.use(function *(){
yield send(this, path.join(__dirname, '/../public/','index.html' )); })
app.use(router.routes())
following code also don't work
router
.get('*', function* () {
yield send(this, __dirname +'/../public/index.html')
})
router.get('*', async function(ctx, next) {
var html = fs.readFileSync(path.resolve('./build/index.html'));
ctx.type = 'html';
ctx.body = html;
})
this works for me
Essentially what you're trying to achieve is server-rendering.
You need to write route configuration with match & RouterContext. react-router has detailed documentation for this.
Server Rendering in react-router
In case of koa, it can roughly be done in this way.
import router from 'koa-router'
import { match, RouterContext } from 'react-router'
const koaRouter = router()
const otherRouter = () => {
return new Promise((resolve, reject) => {
match({ routes, location }, (error, redirectLocation, renderProps) => {
...
..
.
}
}
koaRouter
.use(otherRouter)
I found couple of repos online which seem pretty decent. I haven't verified them though.
breko-hub
koa-react-isomoprhic

Categories

Resources