卜娃娃|nodejs 的融会贯通,你学会了吗?( 二 )

重定向HTTP 标准定义了标识重定向发生时的状态码 , 它也指出了客户端应该检查无限循环 。

  • 300:多重选择
  • 301:永久移动到新位置
  • 302:找到重定向跳转
  • 303:参见其他信息
  • 304:没有改动
  • 305:使用代理
  • 307:临时重定向 const http = require('http'); const https = require('https'); const url = require('url'); // 有很多接续 URLs 的方法 // 构造函数被用来创建一个对象来构成请求对象的声明周期 function Request() { this.maxRedirects = 10; this.redirects = 0; } Request.prototype.get = function (href, callback) { const uri = url.parse(href); // 解析 URLs 成为 Node http 模块使用的格式 , 确定是否使用 HTTPS const options = { host: uri.host, path: uri.path }; const httpGet = uri.protocol === 'http:' ? http.get : https.get; console.log('GET:', href); function processResponse(response) { if (response.statusCode >= 300} else { this.redirects++; // 重定向计数自增 href = http://kandian.youth.cn/index/url.resolve(options.host, response.headers.location); // 使用 url.resolve 确保相对路径的 URLs 转换为绝对路径 URLs return this.get(href, callback); } } response.url = href; response.redirects = this.redirects; console.log('Redirected:', href); function end() { console.log('Connection ended'); callback(this.error, response); } response.on('data', function (data) { console.log('Got data, length:', data.length); }); response.on('end', end.bind(this)); // 绑定回调到 Request 实例 , 确保能拿到实例属性 } httpGet(options, processResponse.bind(this)) .on('error', function (err) { callback(err); }); 复制代码 }; const request = new Request(); request.get('google.com/', function (err, res) { if (err) { console.error(err); } else { console.log( Fetched URL: ${res.url} with ${res.redirects} redirects ); process.exit(); } });
HTTP 代理
  • ISP 使用透明代理使网络更加高效
  • 使用缓存代理服务器减少宽带
  • Web 应用程序的 DevOps 利用他们提升应用程序性能 const http = require('http'); const url = require('url'); http.createServer(function (req, res) { console.log('start request:', req.url); const options = url.parse(req.url); console.log(options); options.headers = req.headers; const proxyRequest = http.request(options, function (proxyResponse) { // 创建请求来复制原始的请求 proxyResponse.on('data', function (chunk) { // 监听数据 , 返回给浏览器 console.log('proxyResponse length:', chunk.length); res.write(chunk, 'binary'); }); proxyResponse.on('end', function () { // 追踪代理请求完成 console.log('proxied request ended'); res.end(); }); res.writeHead(proxyResponse.statusCode, proxyResponse.headers); // 发送头部信息给服务器 }); req.on('data', function (chunk) { // 捕获从浏览器发送到服务器的数据 console.log('in request length:', chunk.length); proxyRequest.write(chunk, 'binary'); }); req.on('end', function () { // 追踪原始的请求什么时候结束 console.log('original request ended'); proxyRequest.end(); }); 复制代码 }).listen(8888); // 监听来自本地浏览器的连接
封装 request-promiseconst https = require('https');const promisify = require('util').promisify;https.get[promisify.custom] = function getAsync(options) {return new Promise((resolve, reject) => {https.get(options, (response) => {response.end = new Promise((resolve) => response.on('end', resolve));resolve(response);}).on('error', reject);});};const rp = promisify(https.get);(async () => {const res = await rp(';page=1');let body = '';res.on('data', (chunk) => body += chunk);await res.end;console.log(body);})();复制代码


推荐阅读