在 Express 中使用中间件功能的正确方法
Correct way to utilize middleware functions in Express
嗨,我使用 express 和 node js 创建了一个代理端点,我让它在一个 get 请求中正常工作,但我想设置多个 get/post 请求端点,并且想知道我在下面所做的是否是继续实施其他端点的正确方法,我对 NodeJS 和 express 很陌生。
我尝试过的是重用
app.use(validateFirebaseIdToken);
然后 app.use(new functionname) 在我调用新的 get 端点之前,我需要在我的每个 bigQuery 方法中重用 decodedIDToken 变量,请记住会有很多不同的 bigQuery我将创建查询方法来为最终用户获取数据
var express = require('express')`
var app = express()
const validateFirebaseIdToken = async (req, res, next) => {`
console.log('Check if request is authorized with Firebase ID token');
if ((!req.headers.authorization || !req.headers.authorization.startsWith('Bearer ')) &&!(req.cookies && req.cookies.__session)) {
console.error('No Firebase ID token was passed as a Bearer token in the Authorization header.',
'Make sure you authorize your request by providing the following HTTP header:',
'Authorization: Bearer <Firebase ID Token>',
'or by passing a "__session" cookie.');
res.status(403).send('Unauthorized');
return;
}
let idToken;
if (req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
console.log('Found "Authorization" header');
// Read the ID Token from the Authorization header.
idToken = req.headers.authorization.split('Bearer ')[1];
} else {
// No cookie
res.status(403).send('Unauthorized');
return;
}
try {
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
console.log('ID Token correctly decoded', decodedIdToken);
req.user = decodedIdToken;
next();
return;
} catch (error) {
console.error('Error while verifying Firebase ID token:', error);
res.status(403).send('Unauthorized');
return;
}
};
const runDailyCategorybigQuery = async (req, res, next) => {
const query = `select count(string_field_3) as Categories, Month(date_field_2) as Month from test.testing_api group by Month`;
const options = {
query: query,
// Location must match that of the dataset(s) referenced in the query.
location: 'US',
useLegacySql: true,
};
// Run the query as a job
const [job] = await bigquery.createQueryJob(options);
console.log(`Job ${job.id} started.`);
console.log(`ID ${req.user.user_id}`);
// Wait for the query to finish
const [rows] = await job.getQueryResults();
res.query = rows;
console.log('Rows:');
rows.forEach(row => console.log(row));
next();
};
const runCategoryMonthsbigQuery = async (req, res, next) => {
const query = `select count(string_field_3) as Categories, Month(date_field_2) as Month from test.testing_api group by Month`;
const options = {
query: query,
// Location must match that of the dataset(s) referenced in the query.
location: 'US',
useLegacySql: true,
};
// Run the query as a job
const [job] = await bigquery.createQueryJob(options);
console.log(`Job ${job.id} started.`);
console.log(`ID ${req.user.user_id}`);
// Wait for the query to finish
const [rows] = await job.getQueryResults();
res.query = rows;
console.log('Rows:');
rows.forEach(row => console.log(row));
next();
};
app.use(validateFirebaseIdToken);
app.use(runDailyCategorybigQuery);
app.get('/getCategories', (req, res) => {
res.json(res.query);
});
//what im thinking of doing
app.use(validateFirebaseIdToken);
app.use(runCategoryMonthsbigQuery);
app.get('/getCategoriesMonth', (req, res) => {
res.json(res.query);
});
您列为 "what I am thinking of doing" 的内容将添加相同的中间件两次(用于 validateFirebaseIdToken)。这不是必需的,因为每个请求都会调用中间件,所以你应该只添加一次。
第二个问题是您将请求处理程序视为中间件。由于所有中间件都会看到每个请求(只要它们接下来调用),那么您将 运行 两个查询,第二个将覆盖第一个。
将您的两个查询中间件函数移至请求处理程序中。例如:
const runDailyCategorybigQuery = async (req, res) => {
...
res.json(res.query);
}
app.get('/getCategories', runDailyCategorybigQuery);
嗨,我使用 express 和 node js 创建了一个代理端点,我让它在一个 get 请求中正常工作,但我想设置多个 get/post 请求端点,并且想知道我在下面所做的是否是继续实施其他端点的正确方法,我对 NodeJS 和 express 很陌生。
我尝试过的是重用
app.use(validateFirebaseIdToken);
然后 app.use(new functionname) 在我调用新的 get 端点之前,我需要在我的每个 bigQuery 方法中重用 decodedIDToken 变量,请记住会有很多不同的 bigQuery我将创建查询方法来为最终用户获取数据
var express = require('express')`
var app = express()
const validateFirebaseIdToken = async (req, res, next) => {`
console.log('Check if request is authorized with Firebase ID token');
if ((!req.headers.authorization || !req.headers.authorization.startsWith('Bearer ')) &&!(req.cookies && req.cookies.__session)) {
console.error('No Firebase ID token was passed as a Bearer token in the Authorization header.',
'Make sure you authorize your request by providing the following HTTP header:',
'Authorization: Bearer <Firebase ID Token>',
'or by passing a "__session" cookie.');
res.status(403).send('Unauthorized');
return;
}
let idToken;
if (req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
console.log('Found "Authorization" header');
// Read the ID Token from the Authorization header.
idToken = req.headers.authorization.split('Bearer ')[1];
} else {
// No cookie
res.status(403).send('Unauthorized');
return;
}
try {
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
console.log('ID Token correctly decoded', decodedIdToken);
req.user = decodedIdToken;
next();
return;
} catch (error) {
console.error('Error while verifying Firebase ID token:', error);
res.status(403).send('Unauthorized');
return;
}
};
const runDailyCategorybigQuery = async (req, res, next) => {
const query = `select count(string_field_3) as Categories, Month(date_field_2) as Month from test.testing_api group by Month`;
const options = {
query: query,
// Location must match that of the dataset(s) referenced in the query.
location: 'US',
useLegacySql: true,
};
// Run the query as a job
const [job] = await bigquery.createQueryJob(options);
console.log(`Job ${job.id} started.`);
console.log(`ID ${req.user.user_id}`);
// Wait for the query to finish
const [rows] = await job.getQueryResults();
res.query = rows;
console.log('Rows:');
rows.forEach(row => console.log(row));
next();
};
const runCategoryMonthsbigQuery = async (req, res, next) => {
const query = `select count(string_field_3) as Categories, Month(date_field_2) as Month from test.testing_api group by Month`;
const options = {
query: query,
// Location must match that of the dataset(s) referenced in the query.
location: 'US',
useLegacySql: true,
};
// Run the query as a job
const [job] = await bigquery.createQueryJob(options);
console.log(`Job ${job.id} started.`);
console.log(`ID ${req.user.user_id}`);
// Wait for the query to finish
const [rows] = await job.getQueryResults();
res.query = rows;
console.log('Rows:');
rows.forEach(row => console.log(row));
next();
};
app.use(validateFirebaseIdToken);
app.use(runDailyCategorybigQuery);
app.get('/getCategories', (req, res) => {
res.json(res.query);
});
//what im thinking of doing
app.use(validateFirebaseIdToken);
app.use(runCategoryMonthsbigQuery);
app.get('/getCategoriesMonth', (req, res) => {
res.json(res.query);
});
您列为 "what I am thinking of doing" 的内容将添加相同的中间件两次(用于 validateFirebaseIdToken)。这不是必需的,因为每个请求都会调用中间件,所以你应该只添加一次。
第二个问题是您将请求处理程序视为中间件。由于所有中间件都会看到每个请求(只要它们接下来调用),那么您将 运行 两个查询,第二个将覆盖第一个。
将您的两个查询中间件函数移至请求处理程序中。例如:
const runDailyCategorybigQuery = async (req, res) => {
...
res.json(res.query);
}
app.get('/getCategories', runDailyCategorybigQuery);