Skip to content

Instantly share code, notes, and snippets.

@knight42
Last active December 8, 2016 08:37
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save knight42/ace33c91d6ddac7b60f8 to your computer and use it in GitHub Desktop.
Save knight42/ace33c91d6ddac7b60f8 to your computer and use it in GitHub Desktop.
naive promisified request
#!/usr/bin/node
"use strict";
const net = require('net');
const url = require('url');
const qs = require('querystring');
function request(opts) {
if(! /^https?:\/\//.test(opts.url)) opts.url = `http://${opts.url}`;
let header = {};
let urlObj = url.parse(opts.url);
header.host = urlObj.hostname;
header.port = urlObj.port || 80;
header.path = urlObj.path ;
let query = qs.stringify(opts.qs);
if(query) header.path += `?${query}`;
header.headers = opts.headers || {};
header.headers['User-Agent'] = header.headers['User-Agent'] || 'Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0';
header.method = (opts.method || 'GET').toUpperCase();
header.form = qs.stringify(opts.form);
return new Promise((resolve, reject) => {
const client = net.createConnection(header.port, header.host, () => {
let req = '';
req += `${header.method} ${header.path} HTTP/1.1\r\n`;
req += `Host: ${header.host}\r\n`;
req += `Accept: */*\r\n`;
req += `Connection: keep-alive\r\n`;
if(header.method === 'POST') {
req += `Content-Type: application/x-www-form-urlencoded\r\n`;
req += `Content-Length: ${header.form.length}\r\n`;
}
Object.keys(header.headers).forEach((key) => {
req += `${key}: ${header.headers[key]}\r\n`;
});
req += '\r\n'
if(header.method === 'POST') {
req += header.form;
}
console.log(req);
client.end(req);
}).on('error', reject);
let chunks = [], size = 0;
let response = {headers: {}, statusText: '', statusCode: '', body: null};
let body = '';
client.on('close', () => {
client.destroy();
})
client.on('data', (chunk) => {
size += chunk.length;
chunks.push(chunk);
body += chunk.toString();
});
client.on('end', () => {
if(! body) return reject(new Error('Empty response'));
let _res = body.split('\r\n\r\n');
_res[0].split('\r\n').forEach((e, i) => {
let _t;
if(i === 0) {
// HTTP/1.0 code text
_t = e.split(' ');
response.statusCode = _t[1];
response.statusText = _t.slice(2).join(' ');
} else {
_t = e.split(': ', 2);
response.headers[_t[0]] = _t[1];
}
});
response.body = Buffer.concat(chunks, size);
resolve(response);
});
})
}
module.exports = request;
request({
url: 'http://ustc.edu.cn',
//url: 'http://mis.teach.ustc.edu.cn',
//url: 'http://mirrors.ustc.edu.cn/node/',
//method: 'HEAD',
//url: 'http://weibo.com/',
//url: 'http://www.baidu.com/s',
//qs: {wd: 'qwe', ie: 'UTF-8', tn: 'baidulocal'},
//// python -m http.server
//url: 'localhost:8000',
//method: 'POST',
//form: {a:123, b:456}
})
.then(data => {
console.log(data);
console.log(data.body);
})
.catch(console.error)
})();
@magicdawn
Copy link

node.js 的模块都会被 function(exports, module, require, __dirname, __filename){ ... }包一层,没必要自己去加一个自执行函数啊

@knight42
Copy link
Author

@magicdawn 写 js 我都是在模板文件上改的, 模板文件要尽可能做到通用.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment