I read https://github.com/fastify/fastify/blob/master/docs/Routes.md
But my router doesn't seems to catch the right url with params
Url : /app/name?id=666&method=3&_=1553342444710
I tried:
fastify.get('/app/:id-:method:*', (request, reply) => {
fastify.get('/app/*', (request, reply) => {
fastify.get('/app/:id-:method:-:_', (request, reply) => {
Try this:
fastify.get('/app/name', {
schema: {
querystring: {
id: { type: 'integer' },
name: { type: 'string' },
_: { type: 'integer' },
}
},
},
(request, reply) => {
...
Related
I have the following route
export default async function (fastify) {
// fastify routes here...
fastify.get(
'/',
{
schema: {
params: {
type: 'object',
properties: {
id: {
type: 'number',
description: 'configuration id',
},
},
},
},
},
async (req) => {
console.log(req.params);
return {};
},
);
}
// Prefix for fastify autoload
export const autoPrefix = `/configuration/:id/jobs`;
How can I set the parameter schema for all of my routes in that function so I don't to duplicate my param schema:
{
params: {
type: 'object',
properties: {
id: {
type: 'number',
description: 'configuration id',
},
},
},
}
I know I can do:
const params = {
type: 'object',
properties: {
id: {
type: 'number',
description: 'configuration id',
},
},
};
fastify.get(
'/',
{
schema: {
params,
},
},
async (req) => {
console.log(req.params);
return {};
},
);
But asking if there is a way that I won't need to do that for each route
Edit: I've opened an issue with a proposal fastify/fastify#4316
You can use the onRoute hook
const fastify = require('fastify')({ logger: true })
const params = {
type: 'object',
properties: {
id: {
type: 'number',
description: 'configuration id'
}
}
}
fastify.addHook('onRoute', function hook (routeOptions) {
if (!routeOptions.schema) {
routeOptions.schema = {}
}
if (!routeOptions.schema.params && routeOptions.path.includes(':id')) {
routeOptions.schema.params = params
}
})
fastify.get('/:id', async (request, reply) => {
return { hello: 'world' }
})
fastify.register(async function plugin (instance, opts) {
instance.post('/foo', async (request, reply) => {
return request.body
})
}, { prefix: '/:id' })
fastify.ready()
Blog Schema:
{
body: { type: String, required: true },
title: { type: String, required: true },
published: { type: String, default: false },
date: { type: Date, default: Date.now },
user: { type: Schema.Types.ObjectId, ref: 'BlogUser' },
comments: [{ type: Schema.Types.ObjectId, ref: 'Comments' }],
likes:[{user:{ type: Schema.Types.ObjectId, ref: 'BlogUser' }}]
}
Like Route for adding a like:
exports.likeBlog = async (req, res) => {
const blog_id = req.params.blog_id;
const user_id = req.body.user_id;
await Blog.findByIdAndUpdate(
blog_id,
{
$push: {
likes: {
user: user_id,
},
},
},
{ new: true },
(err, newBlog) => {
if (err) res.status(422).json(err);
console.log(newBlog);
res.json(newBlog);
}
);
};
Blog Route for reciveing a blog:
exports.getBlogByID = async (req, res) => {
const blog_id = req.params.blog_id;
try {
const blog = await Blog.findById(blog_id)
.populate("comments")
.populate("user");
console.log(blog);
res.json(blog);
} catch (error) {
res.status(401).json(error);
}
};
When I add a like by calling Like route from client, I get a blog with correct amount of likes i.e only 1. But when I request blog from Blog Route it returns me with two objects inside "likes" array, with both same as each other(same id too). Why am I getting such result? Mind you that I call 'Blog Route' after calling 'Like Route'.
It worked fine after I changed "like route" to this:
exports.likeBlog = async (req, res) => {
const blog_id = req.params.blog_id;
const user_id = req.body.user_id;
const blog = await Blog.findById(blog_id);
blog.likes.unshift({ user: user_id });
await blog.save();
Blog.findById(blog_id)
.then((result) => {
res.json(result);
})
.catch((error) => {
res.status(501).json({ error });
});
};
I still don't know what's the difference between the two though.
In my case, one maincategory has many subcategories.
maincategory model defined:
const MainCategorySchema = mongoose.Schema({
mainCategoryName: {
type: String,
unique: true,
required: true,
},
});
subcategory model defined
const SubCategorySchema = mongoose.Schema({
subCategoryName: {
type: String,
unique: true,
required: true,
},
main_category: {
type: mongoose.Schema.Types.ObjectId,
ref: "MainCategory",
},
});
module.exports.getAllSubCategories = function (callback) {
SubCategory.find(callback);
};
route
router.get( "/subCategories",
passport.authenticate("jwt", { session: false }),
(req, res) => {
SubCategory.getAllSubCategories((err, subCategory) => {
if (err) {
let message = "No category";
return res.json({
success: false,
message,
});
} else {
return res.send(subCategory);
}
});
}
);
How can I display mainCategoryName along with subCategoryName?
You need to populate main_category like this:
router.get("/subCategories",
passport.authenticate("jwt", { session: false }), (req, res) => {
SubCategory.find()
.populate("main_category")
.exec((err, subCategory) => {
if (err) {
let message = "No category";
return res.json({
success: false,
message
});
} else {
return res.send(subCategory);
}
});
}
);
I am trying to get data mapped with empid from 2 tables viz-skillsrepo and certifications and render it to frontend,I am getting all data from certifications table,but i need data only of the empid which i send in request
tried using includes method
app.get('/updateprofile/:id', function (req, res) {
db.skillsrepo.find({
where: { employeeId: req.params.id },
include: [
{
model: db.certifications
},
{
model: db.attachments
},
{
model: db.project
}
]
}).then(result => {
if (result != null) {
res.render('updateprofile', {
user: result,
eid: req.params.id,
});
console.log("**********", result)
}
})
});
This is the Schema:
var skillsrepo = exports.skillsrepo = connection.define('skillsrepo', {
firstname: {
type: Sequelize.STRING(23)
},
lastname: {
type: Sequelize.STRING(23)
},
highQual: {
type: Sequelize.STRING(23)
},
fivekeystrenghts: {
type: Sequelize.TEXT
},
domain: {
type: Sequelize.STRING(23)
},
technicalskills: {
type: Sequelize.STRING(23)
},
typesoftesting: {
type: Sequelize.STRING(23)
},
employeeId: {
type: Sequelize.INTEGER(11),
references: {
model: 'employeemastertablee',
key: 'id'
}
}
});
skillsrepo.hasMany(certifications, {
foreignKey: "employeeId"
});
certifications.belongsTo(skillsrepo, {
foreignKey: "employeeId"
});
I'm trying to change a remote method for the Idioma model which only had one parameter (id). This is is the actual functioning code:
Model.remoteMethod('idiomaByOferta', {
description: 'Obtener un idioma por oferta',
http: { path: '/oferta/:id', verb: 'get' },
accepts: [
{ arg: 'id', type: 'string', required: true },
{ arg: 'res', type: 'object', http: { source: 'res' } }
],
returns: {
type: 'Object',
root: true,
default: output_structure
}
});
Model.idiomaByOferta = (id, res, cb) => {
parameterValidatorId(id, err => {
if (err) {
res.status(httpStatus.BAD_REQUEST.code).send(err);
}
});
const conn = Model.app.datasources.db.connector;
commons
.getResultSqlString(conn, sqlEstablecimiento.findIdiomas, [id])
.then(stb => {
cb(null, stb);
})
.catch(err => cb(err, null));
};
Model.afterRemote('idiomaByOferta', async (ctx, result, next) => {
delete ctx.res.req.query.limit;
delete ctx.res.req.query.page;
delete query.limit;
delete query.page;
next();
});
Now I want to include another parameter but I haven't found exactly how to do it with required parameters. I have tried the following but it doesn't work:
Model.remoteMethod('idiomaByOferta', {
description: 'Obtener un idioma por oferta',
http: { path: '/oferta', verb: 'get' },
accepts: [
{ arg: 'id', type: 'string', required: true, http: { source: 'query' }},
{ arg: 'nivel', type: 'string', required: true, http: { source: 'query' }},
{ arg: 'res', type: 'object', http: { source: 'res' } }
],
returns: {
type: 'Object',
root: true,
default: output_structure
}
});
Request url: {{url}}/api/idiomas/oferta?id={{oferta}}&nivel=Inicial
Response:
{
"errors": [
{
"code": 938,
"source": "id",
"detail": "is not allowed"
},
{
"code": 963,
"source": "nivel",
"detail": "is not allowed"
}
]
}
I have also tried doing this:
Model.remoteMethod('idiomaByOferta', {
description: 'Obtener un idioma por oferta',
http: { path: '/oferta/:id/nivel/:nivel', verb: 'get' },
accepts: [
{ arg: 'id', type: 'string', required: true},
{ arg: 'nivel', type: 'string', required: true},
{ arg: 'res', type: 'object', http: { source: 'res' } }
],
returns: {
type: 'Object',
root: true,
default: output_structure
}
});
The request times out and is never completed.
The position of your accepts attributes is important.
In your http attribute, the argument path is optionnal and is useful if you want to change the order of your accepts attributes or simply modify the path name.
What I would do is:
Model.remoteMethod('idiomaByOferta', {
description: 'Obtener un idioma por oferta',
http: { path: '/oferta/:id/:nivel', verb: 'get' },
accepts: [
{ arg: 'id', type: 'string', required: true },
{ arg: 'nivel', type: 'string', required: true},
{ arg: 'res', type: 'object', http: { source: 'res' } }
],
returns: {
type: 'Object',
root: true,
default: output_structure
}
});
Model.idiomaByOferta = (id, nivel, res, cb) => { //add nivel here in second position
parameterValidatorId(id, err => {
if (err) {
res.status(httpStatus.BAD_REQUEST.code).send(err);
}
});
parameterValidatorId(nivel, err => {
if (err) {
res.status(httpStatus.BAD_REQUEST.code).send(err);
}
});
const conn = Model.app.datasources.db.connector;
commons
.getResultSqlString(conn, sqlEstablecimiento.findIdiomas, [id, nivel]) //and use it there, maybe, depending on what your code is doing?
.then(stb => {
cb(null, stb);
})
.catch(err => cb(err, null));
};