基于nodejs 创建一个http server很简单:
const http = require('http');
const server = http.createServer((req, res) => {
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World');
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});
server.listen(3900, () => {
console.log('Server is running on port 3900');
});
createServer方法定义在lib/http.js文件里:Server的具体实现在/lib/_http_server.js文件里,
function createServer(opts, requestListener) {
return new Server(opts, requestListener);
}
function Server(options, requestListener) {
if (!(this instanceof Server)) return new Server(options, requestListener);
.....
storeHTTPOptions.call(this, options);
....
// 这里可以监听connection事件,是因为Server继承了net.Server
this.on('connection', connectionListener);
this.on('listening', setupConnectionsTracking);
...
}
// 继承net.Server,源码在lib/net.js中
ObjectSetPrototypeOf(Server.prototype, net.Server.prototype);
ObjectSetPrototypeOf(Server, net.Server);
函数体中storeHTTPOptions的作用:
- 配置验证: 验证传入的配置选项是否有效
- 默认值设置: 为未提供的选项设置合理的默认值
- 安全配置: 设置头部大小限制、超时等安全参数
- 性能调优: 配置 keep-alive、连接检查等性能相关参数
- 行为控制: 控制 HTTP 解析器的严格程度和头部处理方式
这些配置直接影响 HTTP 服务器的行为、性能和安全性,是服务器初始化的关键步骤。
Server继承自net.Server, net.Server定义了connection事件,当有新的 TCP 连接建立时会自动触发connection.可以理解为这是一种分层设计:net.Server负责TCP连接管理,http.server负责HTTP协议处理. 这也遵循Node.js的事件驱动模式.
当Server收到connection事件的消息时会执行connectionListener,connectionListener实际执行的是connectionListenerInternal,
function connectionListenerInternal(server, socket) {
socket.server = server;
if (server.timeout && typeof socket.setTimeout === 'function')
socket.setTimeout(server.timeout);
socket.on('timeout', socketOnTimeout);
// 分配解析器
const parser = parsers.alloc();
const lenient = server.insecureHTTPParser === undefined ?
isLenient() : server.insecureHTTPParser;
// 初始化解析器
parser.initialize(
HTTPParser.REQUEST,
new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket),
server.maxHeaderSize || 0,
lenient ? kLenientAll : kLenientNone,
server[kConnections],
);
parser.socket = socket;
socket.parser = parser;
// Propagate headers limit from server instance to parser
if (typeof server.maxHeadersCount === 'number') {
parser.maxHeaderPairs = server.maxHeadersCount << 1;
}
const state = {
onData: null,
onEnd: null,
onClose: null,
onDrain: null,
...
};
// 绑定函数,socketOnData函数有5个参数,这里先预设4个
state.onData = socketOnData.bind(undefined,server, socket, parser, state);
....
// socket接收到数据时,数据作为参数d自动传入.等价于执行socketOnData(server, socket, state, parser, d);
socket.on('data', state.onData);
// 设置 onIncoming 回调
parser.onIncoming = parserOnIncoming.bind(undefined,server, socket, state);
......
}
// 参数d是包含http请求数据的Buffer
function socketOnData(server, socket, parser, state, d) {
...
// 将原始字节数据传递给HTTP解析器
const ret = parser.execute(d);
// 处理解析结果
onParserExecuteCommon(server, socket, parser, state, ret, d);
}
socket.on(‘data’)的回调函数通过bind的方式预设了server, socket, parser, state等4个参数,d 是动态变化的数据参数,每次调用时由系统根据实际接收到的数据传入。通过bind预设,避免每次调用时重复传递.
当调用 parser.execute(d) 时,实际调用的是c++底层函数,具体流程如下:

在解析HTTP字节流的过程中,解析器会自动调用这些回调,具体处理细节在_http_common.js里面,
const parsers = new FreeList('parsers', 1000, function parsersCb() {
const parser = new HTTPParser();
cleanParser(parser);
// 1. 解析到头部字段时
parser[kOnHeaders] = parserOnHeaders;
// 2. 所有头部解析完成时
parser[kOnHeadersComplete] = parserOnHeadersComplete;
// 3. 解析到请求体时
parser[kOnBody] = parserOnBody;
// 4. 整个消息解析完成时
parser[kOnMessageComplete] = parserOnMessageComplete;
return parser;
});
具体看所有头部解析完成时的回调parserOnHeadersComplete:
function parserOnHeadersComplete(versionMajor, versionMinor, headers, method,
url, statusCode, statusMessage, upgrade,
shouldKeepAlive) {
// this 指向HTTP解析器对象
const parser = this;
const { socket } = parser;
if (headers === undefined) {
headers = parser._headers;
parser._headers = [];
}
if (url === undefined) {
url = parser._url;
parser._url = '';
}
// Parser is also used by http client
const ParserIncomingMessage = (socket?.server?.[kIncomingMessage]) ||
IncomingMessage;
// 创建IncomingMessage对象,这就是req对象
const incoming = parser.incoming = new ParserIncomingMessage(socket);
// 设置请求对象的各种属性
incoming.httpVersionMajor = versionMajor;
incoming.httpVersionMinor = versionMinor;
incoming.httpVersion = `${versionMajor}.${versionMinor}`;
incoming.joinDuplicateHeaders = socket?.server?.joinDuplicateHeaders ||
parser.joinDuplicateHeaders;
incoming.url = url;
incoming.upgrade = upgrade;
let n = headers.length;
// If parser.maxHeaderPairs <= 0 assume that there's no limit.
if (parser.maxHeaderPairs > 0)
n = MathMin(n, parser.maxHeaderPairs);
incoming._addHeaderLines(headers, n);
if (typeof method === 'number') {
// server only
incoming.method = allMethods[method];
} else {
// client only
incoming.statusCode = statusCode;
incoming.statusMessage = statusMessage;
}
// 传递incoming,也就是req对象
return parser.onIncoming(incoming, shouldKeepAlive);
}
当前头部解析完成之后会执行parser.onIncoming回调,parser.onIncoming回调定义在_http.server.js文件connectionListenerInternal函数中
parser.onIncoming = parserOnIncoming.bind(undefined,server, socket, state);
function parserOnIncoming(server, socket, state, req, keepAlive) {
resetSocketTimeout(server, socket, state);
...
// 这里传入res
const res = new server[kServerResponse](req,
.....
if (!handled) {
// 传入req与res 通知执行 Server执行 request事件
server.emit('request', req, res);
}
return 0; // No special treatment.
}
最后用一张图来总结整个流程:
