前端面试题目 (Node.JS-Express框架)[二]

在 Express 中如何使用 Passport.js 进行身份认证?

Passport.js 是一个 Node.js 的身份验证中间件,它可以很容易地与 Express 集成。下面是一个简单的示例,展示了如何使用 Passport.js 进行基本的身份认证。

安装依赖

bash 复制代码
npm install express passport passport-local

设置 Passport

javascript 复制代码
const express = require('express');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

const app = express();

// 序列化用户会话
passport.serializeUser((user, done) => {
  done(null, user.id);
});

// 反序列化用户会话
passport.deserializeUser((id, done) => {
  User.findById(id, (err, user) => {
    done(err, user);
  });
});

// 使用本地策略
passport.use(new LocalStrategy((username, password, done) => {
  User.findOne({ username: username }, (err, user) => {
    if (err) { return done(err); }
    if (!user) { return done(null, false, { message: 'Incorrect username.' }); }
    if (!user.validPassword(password)) { return done(null, false, { message: 'Incorrect password.' }); }
    return done(null, user);
  });
}));

// 中间件配置
app.use(passport.initialize());
app.use(passport.session());

// 登录路由
app.post('/login', passport.authenticate('local', { failureRedirect: '/login-failure' }), (req, res) => {
  res.redirect('/profile');
});

// 登录失败路由
app.get('/login-failure', (req, res) => {
  res.send('Login failed.');
});

// 需要认证的路由
app.get('/profile', (req, res) => {
  if (!req.isAuthenticated()) {
    return res.status(401).send('Unauthorized');
  }
  res.send(`Hello, ${req.user.username}`);
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

如何在 Express 中集成 GraphQL?

要在 Express 中集成 GraphQL,你需要使用 express-graphql 中间件。

安装依赖

bash 复制代码
npm install express express-graphql graphql

设置 GraphQL

javascript 复制代码
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

const app = express();

// 构建 GraphQL Schema
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

// 根级别的解析器
const root = {
  hello: () => {
    return 'Hello world!';
  },
};

// 将 GraphQL HTTP 中间件应用到 Express
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true, // 启用 GraphiQL 界面
}));

app.listen(4000, () => {
  console.log('Now listening for requests on port 4000');
});

如何在 Express 中实现 CSRF 防护?

你可以使用 csurf 中间件来在 Express 中实现 CSRF 防护。

安装依赖

bash 复制代码
npm install csurf cookie-parser

设置 CSRF 防护

javascript 复制代码
const express = require('express');
const cookieParser = require('cookie-parser');
const csurf = require('csurf');

const app = express();

// 解析 cookies
app.use(cookieParser());

// 创建 CSRF 保护中间件
const csrfProtection = csurf({ cookie: true });

// 应用 CSRF 保护到所有 POST 请求
app.post('/some-route', csrfProtection, (req, res) => {
  res.send('Form submitted successfully');
});

// 提供 CSRF 令牌给前端(例如,通过模板或 API)
app.get('/form', (req, res) => {
  // 将 CSRF 令牌传递给前端
  res.cookie('XSRF-TOKEN', req.csrfToken());
  // 或者通过模板直接渲染
  // res.render('send', { csrfToken: req.csrfToken() });
  res.send(`
    <form action="/some-route" method="post">
      <input type="hidden" name="_csrf" value="${req.csrfToken()}">
      <button type="submit">Submit</button>
    </form>
  `);
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Express 中如何处理文件下载功能?

你可以使用 res.download() 方法来处理文件下载。

javascript 复制代码
const express = require('express');
const path = require('path');

const app = express();

app.get('/download', (req, res) => {
  const filePath = path.join(__dirname, 'example.txt');
  res.download(filePath, 'new-name.txt', (err) => {
    if (err) {
      console.error('Error during file download:', err);
    } else {
      console.log('File downloaded successfully');
    }
  });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Express 中的错误处理中间件如何编写?

错误处理中间件是带有四个参数的中间件函数,第四个参数是 next 的错误处理形式(通常省略或用 err 占位)。

javascript 复制代码
const express = require('express');
const app = express();

// 普通的中间件
app.use((req, res, next) => {
  // 如果有错误发生,传递给下一个错误处理中间件
  const err = new Error('Something broke!');
  err.status = 400; // 设置错误状态码
  next(err);
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(err.status || 500);
  res.json({ message: err.message });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

在 Express 中如何实现用户认证和授权?

用户认证通常通过中间件实现,如之前 Passport.js 示例所示。授权则可以在路由处理函数中检查用户权限。

Express 中如何设置默认的错误处理程序?

默认的错误处理程序是放在所有其他路由之后的错误处理中间件。

javascript 复制代码
const express = require('express');
const app = express();

// 其他路由...

// 默认错误处理程序
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

如何在 Express 中实现简单的表单提交和处理?

你可以使用 body-parser 中间件来解析表单数据。

安装依赖

bash 复制代码
npm install body-parser

处理表单提交

javascript 复制代码
const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// 解析 urlencoded 表单数据
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/submit', (req, res) => {
  const { name, email } = req.body;
  res.send(`Received name: ${name} and email: ${email}`);
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

在 Express.js 中,处理 HTTP 请求头信息、设置模板引擎、使用参数匹配路由以及区分 app.get()app.post() 方法是非常常见的任务。以下是详细的解释和示例:

设置和获取 HTTP 请求头信息

设置请求头信息

通常,客户端(如浏览器)会设置请求头信息,但服务器端可以通过中间件修改响应头信息。

javascript 复制代码
const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.setHeader('Content-Type', 'application/json');
    res.send(JSON.stringify({ message: 'Hello, World!' }));
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});
获取请求头信息

你可以在请求处理函数中通过 req.headers 来获取请求头信息。

javascript 复制代码
app.get('/headers', (req, res) => {
    const userAgent = req.headers['user-agent'];
    res.send(`Your User-Agent is: ${userAgent}`);
});

设置模板引擎

使用 EJS
  1. 安装 EJS:

    bash 复制代码
    npm install ejs
  2. 配置 Express 使用 EJS:

    javascript 复制代码
    const express = require('express');
    const app = express();
    
    app.set('view engine', 'ejs');
    
    app.get('/', (req, res) => {
        res.render('index', { title: 'Hello, EJS!' });
    });
    
    app.listen(3000, () => {
        console.log('Server is running on port 3000');
    });

    views 文件夹中创建一个名为 index.ejs 的文件:

    html 复制代码
    <!DOCTYPE html>
    <html>
    <head>
        <title><%= title %></title>
    </head>
    <body>
        <h1><%= title %></h1>
    </body>
    </html>
使用 Pug (以前称为 Jade)
  1. 安装 Pug:

    bash 复制代码
    npm install pug
  2. 配置 Express 使用 Pug:

    javascript 复制代码
    const express = require('express');
    const app = express();
    
    app.set('view engine', 'pug');
    
    app.get('/', (req, res) => {
        res.render('index', { title: 'Hello, Pug!' });
    });
    
    app.listen(3000, () => {
        console.log('Server is running on port 3000');
    });

    views 文件夹中创建一个名为 index.pug 的文件:

    pug 复制代码
    doctype html
    html
        head
            title= title
        body
            h1= title

使用参数匹配路由

参数匹配路由允许你根据 URL 中的参数动态地处理请求。

javascript 复制代码
app.get('/user/:userId', (req, res) => {
    const userId = req.params.userId;
    res.send(`User ID is: ${userId}`);
});

例如,访问 /user/123 会输出 User ID is: 123

app.get()app.post() 方法的区别

  • app.get():用于处理 HTTP GET 请求。GET 请求通常用于请求数据,而不是提交数据。

    javascript 复制代码
    app.get('/data', (req, res) => {
        res.send('This is a GET request');
    });
  • app.post():用于处理 HTTP POST 请求。POST 请求通常用于提交数据,如表单数据或文件上传。

    javascript 复制代码
    app.post('/submit', (req, res) => {
        const body = req.body; // 假设你使用了 body-parser 中间件
        res.send(`Received data: ${body.data}`);
    });

    注意:要解析 POST 请求体中的数据,你需要使用中间件,如 express.json()express.urlencoded({ extended: true })

    javascript 复制代码
    const express = require('express');
    const app = express();
    
    app.use(express.json()); // 用于解析 JSON 数据
    app.use(express.urlencoded({ extended: true })); // 用于解析 URL 编码的数据
    
    app.post('/submit', (req, res) => {
        const body = req.body;
        res.send(`Received data: ${body.data}`);
    });
    
    app.listen(3000, () => {
        console.log('Server is running on port 3000');
    });

以上就是 Express.js 中设置和获取 HTTP 请求头信息、设置模板引擎、使用参数匹配路由以及区分 app.get()app.post() 方法的基本用法。

1. 在 Express 中如何处理 JSON 格式的请求体?

使用 express.json() 中间件可以解析 JSON 格式的请求体,并将其挂载到 req.body

javascript 复制代码
const express = require('express');
const app = express();

app.use(express.json());

app.post('/data', (req, res) => {
  console.log(req.body); // 解析后的 JSON 数据
  res.send('JSON Received');
});

app.listen(3000, () => console.log('Server running on port 3000'));

2. Express 中的 app.set() 方法有什么作用?

app.set() 用于设置 Express 应用的全局变量或配置项,供应用中的其他部分访问。

示例
javascript 复制代码
const express = require('express');
const app = express();

// 设置视图引擎
app.set('view engine', 'pug');
app.set('views', './views');

// 访问配置项
console.log(app.get('view engine')); // 'pug'

3. Express 中的请求对象 req 包含哪些常用属性?

  • req.body :请求体数据(需中间件支持,如 express.json())。
  • req.params:路由路径参数。
  • req.query:查询字符串参数。
  • req.headers:请求头。
  • req.method:HTTP 请求方法。
  • req.url:请求路径。
示例
javascript 复制代码
app.get('/user/:id', (req, res) => {
  console.log(req.params.id); // 路由参数
  console.log(req.query.sort); // 查询参数
  res.send('Request details logged');
});

4. Express 中的响应对象 res 有哪些常用方法?

  • res.send():发送响应数据。
  • res.json():发送 JSON 格式数据。
  • res.status():设置 HTTP 状态码。
  • res.redirect():重定向到指定 URL。
  • res.render():渲染模板引擎输出。
示例
javascript 复制代码
app.get('/json', (req, res) => res.json({ success: true }));
app.get('/redirect', (req, res) => res.redirect('/new-page'));

5. 在 Express 中如何处理 404 错误?

通过捕获所有未匹配路由并返回 404 错误。

javascript 复制代码
app.use((req, res, next) => {
  res.status(404).send('Page Not Found');
});

6. 什么是 Express 中的路由方法链式调用?

通过链式调用同一路径的多个 HTTP 方法(如 getpost)来组织路由。

示例
javascript 复制代码
app.route('/user')
  .get((req, res) => res.send('Get User'))
  .post((req, res) => res.send('Create User'))
  .put((req, res) => res.send('Update User'));

7. 如何在 Express 中使用 app.use() 方法?

app.use() 用于注册中间件或绑定处理函数,可应用于全局或特定路径。

示例
javascript 复制代码
// 全局中间件
app.use((req, res, next) => {
  console.log('Request received');
  next();
});

// 路径绑定
app.use('/secure', (req, res, next) => {
  console.log('Secure route');
  next();
});

8. Express 中的模板引擎有哪些?如何选择?

常用模板引擎
  • Pug:简洁、语法直观。
  • EJS:嵌入 JavaScript,灵活易用。
  • Handlebars:结构化模板,适合复杂视图。
选择依据
  • Pug:适合需要简洁语法的项目。
  • EJS:适合需要直接嵌入逻辑的场景。
  • Handlebars:适合强调分离逻辑和视图的项目。

9. 在 Express 中如何处理静态文件的缓存?

通过 express.static() 设置静态文件目录,并自定义缓存设置。

示例
javascript 复制代码
app.use(express.static('public', {
  maxAge: '1d', // 缓存 1 天
}));

10. Express 的中间件有哪些类型?

  1. 应用级中间件 :绑定到 app,如 app.use()
  2. 路由级中间件:绑定到路由实例。
  3. 错误处理中间件 :处理错误,形参包含 err
  4. 内置中间件 :如 express.json()express.static()
  5. 第三方中间件 :如 corsbody-parser

11. 在 Express 中如何使用路由器 (Router) 模块化路由?

通过 express.Router() 创建独立路由模块。

示例

创建路由模块:userRoutes.js

javascript 复制代码
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => res.send('Get Users'));
router.post('/', (req, res) => res.send('Create User'));

module.exports = router;

主文件:app.js

javascript 复制代码
const express = require('express');
const userRoutes = require('./userRoutes');
const app = express();

app.use('/users', userRoutes);

app.listen(3000, () => console.log('Server running on port 3000'));

Express Generator

Express Generator 是一个命令行工具,可以快速生成一个具有基本目录结构和文件的 Express 应用。这个工具能够自动化地创建项目结构,包括主要的服务器文件、路由文件、以及配置文件等,从而帮助开发者节省初始设置项目的时间。

要使用 Express Generator,你需要先全局安装它(如果尚未安装):

bash 复制代码
npm install -g express-generator

然后,你可以使用以下命令来创建一个新的 Express 项目:

bash 复制代码
express myapp

其中 myapp 是你的项目名称。执行这个命令后,Express Generator 会在当前目录下创建一个名为 myapp 的新目录,并在其中生成一个基本的 Express 应用结构。

app.listen() 方法

在 Express 中,app.listen() 方法用于启动 HTTP 服务器并监听指定的端口。这个方法通常是在所有路由和中间件配置完成后调用的。例如:

javascript 复制代码
const express = require('express');
const app = express();
const port = 3000;

// 配置路由和中间件
// ...

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

在这个例子中,app.listen(port, callback) 方法启动了一个监听在 3000 端口的 HTTP 服务器,并在服务器启动时打印了一条消息到控制台。

路由参数

Express 中的路由参数(也称为动态路由)允许你捕获 URL 片段的值,并将其作为请求对象(req)的属性。这对于构建 RESTful API 或需要根据 URL 动态生成内容的网站非常有用。例如:

javascript 复制代码
app.get('/user/:id', (req, res) => {
  res.send(`User ID is ${req.params.id}`);
});

在这个例子中,:id 是一个路由参数,它捕获了 URL 中 /user/ 后面的部分,并将其存储在 req.params.id 中。

静态文件中间件

Express 提供了 express.static 中间件来提供静态资源(如 HTML 文件、图片、CSS 样式等)。这个中间件通常放在所有路由定义之前,以便为静态文件请求提供服务。例如:

javascript 复制代码
app.use(express.static('public'));

在这个例子中,express.static 中间件被配置为从 public 目录提供静态文件。如果客户端请求一个静态文件(如 /images/logo.png),Express 会查找 public/images/logo.png 并将其发送给客户端。

中间件

Express 中间件是一堆方法,可以接收客户端发来的请求、可以对请求做出响应,也可以将请求继续交给下一个中间件继续处理。中间件在 Express 应用中扮演着非常重要的角色,它们可以用于执行各种任务,如解析请求体、处理跨域请求、验证用户身份等。

要使用中间件,你可以使用 app.use() 方法将其添加到应用中。中间件函数通常有三个参数:req(请求对象)、res(响应对象)和 next(一个函数,用于将控制权传递给下一个中间件)。例如:

javascript 复制代码
app.use((req, res, next) => {
  console.log('Request received');
  next(); // 将控制权传递给下一个中间件或路由
});

创建路由

在 Express 中创建路由非常简单。你可以使用 app.get()app.post()app.put()app.delete() 等方法定义不同类型的 HTTP 请求路由。这些方法接受两个参数:一个是 URL 路径模式,另一个是处理该请求的回调函数(也称为路由处理函数)。例如:

javascript 复制代码
app.get('/', (req, res) => {
  res.send('Hello, World!');
});

app.post('/submit-form', (req, res) => {
  res.send('Form has been submitted!');
});

Express 框架的基本使用步骤

  1. 导入 Express 框架 :使用 require('express') 导入 Express 模块。
  2. 创建应用实例 :通过调用 express() 函数创建一个 Express 应用实例。
  3. 配置中间件和路由 :使用 app.use() 添加中间件,使用 app.get()app.post() 等方法定义路由。
  4. 启动服务器 :使用 app.listen() 方法启动 HTTP 服务器并监听指定端口。

Express.js 和 Koa.js 框架的区别

  1. 设计理念:Express 的设计理念是"约定优于配置",注重快速开发和易用性;而 Koa 的设计理念是"中间件优先",提供了更加灵活和可控的中间件机制。
  2. 异步编程方式:Express 使用回调函数处理异步操作,而 Koa 则采用基于 Promise 的异步编程方式(从 v2 版本开始支持 async/await)。
  3. 错误处理:Express 使用中间件来处理错误,而 Koa 则使用 try/catch 语句和 async/await 来捕获和处理错误。
  4. 社区和生态系统:Express 拥有更大的社区和更丰富的第三方中间件和库支持,而 Koa 则相对较为年轻,但也在不断发展壮大。

综上所述,Express 和 Koa 都是优秀的 Node.js Web 框架,选择哪个框架取决于你的具体需求和偏好。如果你需要快速搭建一个 Web 应用并希望利用丰富的社区资源和中间件支持,那么 Express 是一个不错的选择;如果你需要更灵活的中间件机制和更现代的异步编程方式,那么 Koa 可能更适合你。

相关推荐
加班是不可能的,除非双倍日工资7 分钟前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi41 分钟前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip1 小时前
vite和webpack打包结构控制
前端·javascript
excel1 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国2 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼2 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy2 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT2 小时前
promise & async await总结
前端
Jerry说前后端2 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天2 小时前
A12预装app
linux·服务器·前端