在Express中利用中间件功能的正确方法

时间:2019-07-14 20:02:05

标签: node.js express middleware endpoint

您好,我通过使用带有节点js的express创建代理端点,我让它可以正确处理一个get请求,但是我想设置多个get / post请求端点,想知道我在下面所做的是否是正确的携带方式继续实现其他端点,NodeJS和express都是新功能。

我在尝试重用

app.use(validateFirebaseIdToken);

然后调用app.use(new functionname)(在我调用新的get端点之前),我需要在我的每个bigQuery方法中重用解码的IDToken变量,请记住,我将有很多不同的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);
});

1 个答案:

答案 0 :(得分:0)

您列出为“我正在考虑做的事情”将两次添加相同的中间件(对于validateFirebaseIdToken)。这不是必需的,因为将在每个请求上调用中间件,因此您只应添加一次即可。

第二个问题是您将请求处理程序视为中间件。由于每个请求都会被所有中间件看到(只要它们调用下一个),那么您将同时运行两个查询,第二个查询将覆盖第一个查询。

将您的两个查询中间件功能移至请求处理程序中。例如:

const runDailyCategorybigQuery = async (req, res) => {
  ...
  res.json(res.query);
}

app.get('/getCategories', runDailyCategorybigQuery);