阿里云主机折上折
  • 微信号
Current Site:Index > Detailed explanation of request and response objects

Detailed explanation of request and response objects

Author:Chuan Chen 阅读数:5992人阅读 分类: Node.js

Request Object (Request)

The Express request object (commonly referred to as req) encapsulates the details of an HTTP request. It extends Node.js's http.IncomingMessage object and adds Express-specific properties and methods.

Common Properties

  1. req.params: An object containing route parameters
app.get('/users/:userId', (req, res) => {
  console.log(req.params.userId); // Get the userId parameter from the route
});
  1. req.query: Contains the parsed query string
// Request URL is /search?q=express&page=2
app.get('/search', (req, res) => {
  console.log(req.query.q);      // "express"
  console.log(req.query.page);   // "2"
});
  1. req.body: Contains request body data (requires body-parser middleware)
const bodyParser = require('body-parser');
app.use(bodyParser.json());

app.post('/login', (req, res) => {
  console.log(req.body.username); // Get the username from the POST request
});
  1. req.headers: Contains the request headers object
app.get('/', (req, res) => {
  console.log(req.headers['user-agent']); // Get the User-Agent header
});
  1. req.cookies: Contains cookies sent by the client (requires cookie-parser middleware)
const cookieParser = require('cookie-parser');
app.use(cookieParser());

app.get('/', (req, res) => {
  console.log(req.cookies.sessionId); // Get the cookie named sessionId
});

Common Methods

  1. req.get(field): Get the specified HTTP request header
const host = req.get('Host');
  1. req.is(type): Check if the request's Content-Type matches the given type
if (req.is('application/json')) {
  // Handle JSON request
}
  1. req.accepts(types): Check if the client accepts the specified response type
// Client Accept: text/html,application/xhtml+xml
req.accepts('html');     // "html"
req.accepts('json');     // false

Response Object (Response)

The Express response object (commonly referred to as res) is used to send responses to the client. It extends Node.js's http.ServerResponse object and adds Express-specific methods.

Common Methods

  1. res.status(code): Set the HTTP status code
res.status(404).send('Not Found');
  1. res.send([body]): Send an HTTP response
res.send('Hello World');          // Send text
res.send({ user: 'tobi' });      // Send JSON
res.send('<p>some html</p>');    // Send HTML
  1. res.json([body]): Send a JSON response
res.json({ username: '张三' });
  1. res.render(view [, locals] [, callback]): Render a view template
// Using a template engine (e.g., EJS)
res.render('index', { title: 'Express' });
  1. res.redirect([status,] path): Redirect the request
res.redirect('/foo/bar');
res.redirect(301, 'http://example.com');
  1. res.set(field [, value]): Set response headers
res.set('Content-Type', 'text/plain');
res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123'
});
  1. res.cookie(name, value [, options]): Set a cookie
res.cookie('rememberme', '1', { 
  maxAge: 900000, 
  httpOnly: true 
});
  1. res.download(path [, filename] [, options] [, fn]): Transfer a file as an attachment
res.download('/report-12345.pdf');
res.download('/report-12345.pdf', 'report.pdf');

Chaining Response Methods

Express response methods support chaining:

res.status(201)
   .set('X-Custom-Header', 'value')
   .cookie('loggedIn', 'true')
   .json({ success: true });

Advanced Usage of Request and Response Objects

Custom Middleware for Request Processing

You can create middleware to preprocess the request object:

app.use((req, res, next) => {
  // Add custom properties
  req.requestTime = new Date().toISOString();
  next();
});

app.get('/', (req, res) => {
  res.send(`Request received at: ${req.requestTime}`);
});

Streaming Response Handling

For large files or streaming data, you can use streaming responses:

const fs = require('fs');

app.get('/video', (req, res) => {
  const videoPath = './big-video.mp4';
  const stat = fs.statSync(videoPath);
  const fileSize = stat.size;
  const range = req.headers.range;
  
  if (range) {
    // Handle partial content requests (206 status code)
    const parts = range.replace(/bytes=/, "").split("-");
    const start = parseInt(parts[0], 10);
    const end = parts[1] ? parseInt(parts[1], 10) : fileSize-1;
    
    res.writeHead(206, {
      'Content-Range': `bytes ${start}-${end}/${fileSize}`,
      'Accept-Ranges': 'bytes',
      'Content-Length': end-start+1,
      'Content-Type': 'video/mp4'
    });
    
    fs.createReadStream(videoPath, {start, end}).pipe(res);
  } else {
    res.writeHead(200, {
      'Content-Length': fileSize,
      'Content-Type': 'video/mp4'
    });
    fs.createReadStream(videoPath).pipe(res);
  }
});

Content Negotiation

Return different response formats based on the client's Accept header:

app.get('/api/user', (req, res) => {
  const user = { name: '张三', age: 30 };
  
  res.format({
    'text/plain': () => {
      res.send(`${user.name}, ${user.age}`);
    },
    'text/html': () => {
      res.send(`<h1>${user.name}</h1><p>Age: ${user.age}</p>`);
    },
    'application/json': () => {
      res.json(user);
    },
    default: () => {
      res.status(406).send('Not Acceptable');
    }
  });
});

Error Handling Middleware

Use request and response objects to handle errors:

app.get('/error', (req, res, next) => {
  const err = new Error('Something went wrong');
  err.status = 500;
  next(err);
});

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(err.status || 500);
  res.json({
    error: {
      message: err.message,
      status: err.status,
      path: req.path
    }
  });
});

Extending Request and Response Objects

Custom Request Properties

You can extend the request object to add custom properties:

app.use((req, res, next) => {
  // Add an isAuthenticated method
  req.isAuthenticated = function() {
    return !!req.session.userId;
  };
  next();
});

app.get('/profile', (req, res) => {
  if (req.isAuthenticated()) {
    res.send('Welcome to your profile');
  } else {
    res.redirect('/login');
  }
});

Extending the Response Object

Similarly, you can extend the response object:

app.use((req, res, next) => {
  // Add a success method
  res.success = function(data) {
    return this.json({
      success: true,
      data: data
    });
  };
  
  // Add an error method
  res.error = function(message, code = 400) {
    return this.status(code).json({
      success: false,
      error: message
    });
  };
  
  next();
});

app.get('/api/data', (req, res) => {
  try {
    const data = getSomeData();
    res.success(data);
  } catch (err) {
    res.error(err.message);
  }
});

Performance Optimization Tips

Use res.append() Instead of Multiple set Calls

// Not recommended
res.set('X-First', '1');
res.set('X-Second', '2');

// Recommended
res.append('X-First', '1');
res.append('X-Second', '2');

Use res.type() to Simplify Content-Type Setting

// Instead of
res.set('Content-Type', 'text/html');

// Use
res.type('html');

Leverage res.vary() for Cache Optimization

app.get('/content', (req, res) => {
  res.vary('User-Agent').render('content');
});

Use res.location() for Safe Redirects

app.post('/login', (req, res) => {
  // Validation logic...
  res.location('/dashboard').status(302).end();
});

Practical Application Scenarios

File Upload Handling

const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('avatar'), (req, res) => {
  // req.file contains information about the uploaded file
  console.log(req.file);
  
  // req.body contains text fields
  console.log(req.body);
  
  res.send('Upload successful');
});

Implementing a RESTful API

// Get a list of resources
app.get('/api/users', (req, res) => {
  const users = getUsers();
  res.json(users);
});

// Get a single resource
app.get('/api/users/:id', (req, res) => {
  const user = getUserById(req.params.id);
  if (user) {
    res.json(user);
  } else {
    res.status(404).json({ error: 'User not found' });
  }
});

// Create a resource
app.post('/api/users', express.json(), (req, res) => {
  const newUser = createUser(req.body);
  res.status(201).json(newUser);
});

// Update a resource
app.put('/api/users/:id', express.json(), (req, res) => {
  const updatedUser = updateUser(req.params.id, req.body);
  if (updatedUser) {
    res.json(updatedUser);
  } else {
    res.status(404).json({ error: 'User not found' });
  }
});

// Delete a resource
app.delete('/api/users/:id', (req, res) => {
  if (deleteUser(req.params.id)) {
    res.status(204).end();
  } else {
    res.status(404).json({ error: 'User not found' });
  }
});

WebSocket Handshake Handling

const WebSocket = require('ws');

const server = app.listen(3000);
const wss = new WebSocket.Server({ server });

wss.on('connection', (ws, req) => {
  // req is the HTTP request object
  console.log('Client connected from:', req.connection.remoteAddress);
  
  ws.on('message', (message) => {
    console.log('Received:', message);
  });
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.