Skip to content
On this page

Express请求与响应

在Express中,请求(req)和响应(res)对象是处理HTTP请求的核心。理解这两个对象的属性和方法对于开发Express应用至关重要。

请求对象(req)

请求对象(req)代表HTTP请求,包含请求的查询字符串、参数、body、HTTP头等信息。

请求路径信息

javascript
app.get('/users/:id', (req, res) => {
  console.log(req.path);        // 请求路径,如 '/users/123'
  console.log(req.url);         // 完整URL,包括查询参数
  console.log(req.baseUrl);     // 路由匹配的URL路径
  console.log(req.originalUrl); // 原始请求URL
  console.log(req.method);      // HTTP方法,如 'GET', 'POST'
});

请求参数

路由参数(req.params)

javascript
// GET /users/123/books/456
app.get('/users/:userId/books/:bookId', (req, res) => {
  console.log(req.params.userId); // '123'
  console.log(req.params.bookId); // '456'
  res.send(req.params);
});

查询参数(req.query)

javascript
// GET /search?q=express&sort=asc&category=nodejs
app.get('/search', (req, res) => {
  console.log(req.query.q);        // 'express'
  console.log(req.query.sort);     // 'asc'
  console.log(req.query.category); // 'nodejs'
  
  // 处理可选参数
  const page = req.query.page || 1;
  const limit = req.query.limit || 10;
  
  res.json({
    query: req.query,
    pagination: { page: parseInt(page), limit: parseInt(limit) }
  });
});

请求体参数(req.body)

javascript
// 需要中间件解析请求体
app.use(express.json());           // 解析JSON
app.use(express.urlencoded({ extended: true })); // 解析URL编码

app.post('/users', (req, res) => {
  console.log(req.body.name);    // 从请求体获取数据
  console.log(req.body.email);   // 从请求体获取数据
  
  res.json({ message: 'User created', user: req.body });
});

请求头信息

javascript
app.get('/headers', (req, res) => {
  console.log(req.headers);              // 所有请求头
  console.log(req.headers['content-type']); // 特定请求头
  console.log(req.headers['user-agent']);   // 用户代理
  console.log(req.headers['authorization']); // 认证信息
  
  // 获取IP地址
  console.log(req.ip);                  // 客户端IP
  console.log(req.ips);                 // 信任代理时的IP数组
  
  // 获取主机信息
  console.log(req.hostname);            // 主机名
  console.log(req.protocol);            // 协议 (http/https)
  console.log(req.secure);              // 是否HTTPS
  
  res.json({
    ip: req.ip,
    hostname: req.hostname,
    protocol: req.protocol,
    headers: req.headers
  });
});

请求方法和状态

javascript
app.all('/all-methods', (req, res) => {
  console.log(req.method);              // HTTP方法
  console.log(req.accepts('json'));     // 检查是否接受JSON
  console.log(req.accepts(['json', 'text'])); // 检查接受的格式
  console.log(req.get('Content-Type')); // 获取特定头信息
  
  // 检查内容类型
  if (req.is('json')) {
    console.log('Request is JSON');
  } else if (req.is('urlencoded')) {
    console.log('Request is URL encoded');
  }
  
  res.send(`Method: ${req.method}`);
});

响应对象(res)

响应对象(res)表示HTTP响应,Express应用在处理请求时发送给客户端。

基本响应方法

res.send() - 发送响应

javascript
app.get('/send', (req, res) => {
  // 发送字符串
  res.send('Hello World');
  
  // 发送对象
  res.send({ message: 'Hello', status: 'success' });
  
  // 发送数组
  res.send([1, 2, 3]);
  
  // 发送状态码
  res.status(404).send('Not Found');
});

res.json() - 发送JSON响应

javascript
app.get('/json', (req, res) => {
  // 自动设置Content-Type为application/json
  res.json({ 
    message: 'Hello JSON',
    timestamp: new Date().toISOString(),
    data: [1, 2, 3]
  });
  
  // 发送数组
  res.json([1, 2, 3, 4]);
  
  // 发送null或undefined
  res.json(null);
});

res.jsonp() - 发送JSONP响应

javascript
app.get('/jsonp', (req, res) => {
  // 支持JSONP回调
  res.jsonp({
    message: 'Hello JSONP',
    data: { id: 1, name: 'Example' }
  });
});

响应状态码

javascript
app.get('/status', (req, res) => {
  // 设置状态码
  res.status(201).send('Created');        // 201 Created
  res.status(400).json({ error: 'Bad Request' }); // 400 Bad Request
  res.status(404).send('Not Found');      // 404 Not Found
  res.status(500).send('Server Error');   // 500 Server Error
  
  // 使用状态码方法
  res.sendStatus(200); // 发送状态码文本
});

响应头设置

javascript
app.get('/headers', (req, res) => {
  // 设置响应头
  res.set('Content-Type', 'text/html');
  res.set({
    'X-API-Key': 'foobar',
    'Content-Type': 'application/json'
  });
  
  // 链式调用
  res
    .set('X-Custom-Header', 'value')
    .status(200)
    .json({ message: 'With custom headers' });
  
  // 重定向头
  res.location('/new-path').send('Redirecting...');
});

重定向响应

javascript
app.get('/redirect', (req, res) => {
  // 临时重定向 (302)
  res.redirect('/new-location');
  
  // 指定状态码的重定向
  res.redirect(301, '/permanently-moved'); // 永久重定向
  
  // 重定向到外部URL
  res.redirect('https://example.com');
  
  // 相对路径重定向
  res.redirect('back'); // 重定向到Referer或Referrer头
});

视图渲染

javascript
// 设置模板引擎
app.set('view engine', 'ejs');
app.set('views', './views');

app.get('/render', (req, res) => {
  // 渲染视图模板
  res.render('index', { 
    title: 'My Page',
    message: 'Hello from template',
    users: [{ name: 'John' }, { name: 'Jane' }]
  });
});

文件响应

javascript
app.get('/download', (req, res) => {
  // 下载文件
  res.download('./files/report.pdf', 'report.pdf');
});

app.get('/file', (req, res) => {
  // 发送文件
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.get('/attachment', (req, res) => {
  // 作为附件发送
  res.attachment('filename.txt');
  res.send('File content');
});

高级请求处理

Cookie处理

javascript
// 需要cookie-parser中间件
const cookieParser = require('cookie-parser');
app.use(cookieParser());

app.get('/cookies', (req, res) => {
  console.log(req.cookies);        // 所有cookies
  console.log(req.cookies.username); // 特定cookie
  
  // 设置cookie
  res.cookie('username', 'john', {
    maxAge: 900000, // 15分钟
    httpOnly: true,
    secure: true    // 仅HTTPS
  });
  
  res.send('Cookie set');
});

// 清除cookie
app.get('/clear-cookie', (req, res) => {
  res.clearCookie('username');
  res.send('Cookie cleared');
});

会话处理

javascript
// 需要express-session中间件
const session = require('express-session');
app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: false } // 在生产环境中设为true
}));

app.get('/session', (req, res) => {
  if (req.session.views) {
    req.session.views++;
    res.send(`Views: ${req.session.views}`);
  } else {
    req.session.views = 1;
    res.send('Welcome to the session demo. Refresh page!');
  }
});

高级响应模式

流式响应

javascript
const fs = require('fs');

app.get('/stream', (req, res) => {
  const stream = fs.createReadStream('./large-file.txt');
  stream.pipe(res);
});

条件响应

javascript
app.get('/conditional', (req, res) => {
  // 检查请求是否可以接受JSON
  if (req.accepts('json')) {
    res.json({ message: 'JSON response' });
  } else if (req.accepts('html')) {
    res.send('<h1>HTML response</h1>');
  } else {
    res.type('txt').send('Plain text response');
  }
});

响应格式化

javascript
app.get('/format', (req, res) => {
  res.format({
    'text/plain': () => {
      res.send('Hello World');
    },
    
    'text/html': () => {
      res.send('<p>Hello World</p>');
    },
    
    'application/json': () => {
      res.json({ message: 'Hello World' });
    },
    
    'default': () => {
      res.status(406).send('Not Acceptable');
    }
  });
});

请求和响应最佳实践

1. 错误处理

javascript
app.get('/error-handling', (req, res, next) => {
  try {
    // 可能出错的代码
    const result = riskyOperation();
    res.json({ result });
  } catch (error) {
    next(error); // 传递给错误处理中间件
  }
});

2. 数据验证

javascript
const validateUser = (req, res, next) => {
  const { name, email } = req.body;
  
  if (!name || !email) {
    return res.status(400).json({ 
      error: 'Name and email are required' 
    });
  }
  
  next(); // 验证通过,继续执行
};

app.post('/users', validateUser, (req, res) => {
  res.json({ message: 'User created successfully' });
});

3. 响应缓存

javascript
app.get('/cached', (req, res) => {
  // 设置缓存头
  res.set({
    'Cache-Control': 'public, max-age=3600', // 缓存1小时
    'ETag': 'unique-identifier'
  });
  
  res.json({ data: 'cached data', timestamp: Date.now() });
});

通过掌握请求和响应对象的各种属性和方法,可以构建功能强大且灵活的Express应用,有效处理各种HTTP请求和响应场景。