okay fastify and express seem to work again

This commit is contained in:
Jarred Sumner
2024-10-06 07:11:18 -07:00
parent a660692743
commit deb44aa80b
7 changed files with 94 additions and 15 deletions

View File

@@ -12,6 +12,7 @@
"eventemitter3": "^5.0.0",
"execa": "^8.0.1",
"fast-glob": "3.3.1",
"fastify": "^5.0.0",
"fdir": "^6.1.0",
"mitata": "^0.1.6",
"string-width": "7.1.0",

View File

@@ -0,0 +1,13 @@
import express from "express";
const app = express();
const port = 3000;
var i = 0;
app.get("/", (req, res) => {
res.send("Hello World!" + i++);
});
app.listen(port, () => {
console.log(`Express app listening at http://localhost:${port}`);
});

View File

@@ -0,0 +1,20 @@
import Fastify from "fastify";
const fastify = Fastify({
logger: false,
});
fastify.get("/", async (request, reply) => {
return { hello: "world" };
});
const start = async () => {
try {
await fastify.listen({ port: 3000 });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();

View File

@@ -440,7 +440,7 @@ public:
bool sendTerminatingChunk(bool closeConnection = false) {
writeStatus(HTTP_200_OK);
HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_WRITE_CALLED)) {
if (!(httpResponseData->state & (HttpResponseData<SSL>::HTTP_WRITE_CALLED | HttpResponseData<SSL>::HTTP_END_CALLED))) {
/* Write mark on first call to write */
writeMark();
@@ -469,7 +469,7 @@ public:
HttpResponseData<SSL> *httpResponseData = getHttpResponseData();
if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_WRITE_CALLED)) {
if (!(httpResponseData->state & (HttpResponseData<SSL>::HTTP_WRITE_CALLED | HttpResponseData<SSL>::HTTP_END_CALLED))) {
/* Write mark on first call to write */
writeMark();
@@ -477,9 +477,14 @@ public:
httpResponseData->state |= HttpResponseData<SSL>::HTTP_WRITE_CALLED;
}
Super::write("\r\n", 2);
writeUnsignedHex((unsigned int) data.length());
Super::write("\r\n", 2);
// This happens if they call send, include a content-length header
if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_END_CALLED)) {
writeUnsignedHex((unsigned int) data.length());
Super::write("\r\n", 2);
}
auto [written, failed] = Super::write(data.data(), (int) data.length());
/* Reset timeout on each sended chunk */

View File

@@ -5875,7 +5875,7 @@ pub const NodeHTTPResponse = struct {
}
fn handleEndedIfNecessary(state: uws.State, globalObject: *JSC.JSGlobalObject) bool {
if (state.isHttpEndCalled()) {
if (!state.isResponsePending()) {
globalObject.ERR_HTTP_HEADERS_SENT("Stream is already ended", .{}).throw();
return true;
}
@@ -6110,7 +6110,7 @@ pub const NodeHTTPResponse = struct {
}
const state = this.response.state();
if (state.isHttpEndCalled()) {
if (!state.isResponsePending()) {
globalObject.ERR_STREAM_WRITE_AFTER_END("Stream already ended", .{}).throw();
return .zero;
}
@@ -6118,7 +6118,7 @@ pub const NodeHTTPResponse = struct {
const input_value = if (arguments.len > 0) arguments[0] else .undefined;
var encoding_value = if (arguments.len > 1) arguments[1] else .undefined;
const callback_value = brk: {
if (encoding_value != .undefined and encoding_value.isCallable(globalObject.vm())) {
if ((encoding_value != .null and encoding_value != .undefined) and encoding_value.isCallable(globalObject.vm())) {
encoding_value = .undefined;
break :brk arguments[1];
}
@@ -6135,9 +6135,8 @@ pub const NodeHTTPResponse = struct {
};
const string_or_buffer: JSC.Node.StringOrBuffer = brk: {
if (input_value == .null) {
globalObject.ERR_STREAM_NULL_VALUES("Cannot write null value to stream", .{}).throw();
return .zero;
if (input_value == .null or input_value == .undefined) {
break :brk JSC.Node.StringOrBuffer.empty;
}
var encoding: JSC.Node.Encoding = .utf8;
@@ -6177,7 +6176,7 @@ pub const NodeHTTPResponse = struct {
}
if (is_end and bytes.len == 0 and write_offset == 0) {
this.response.endWithoutBody(state.isHttpConnectionClose());
this.response.endStream(state.isHttpConnectionClose());
this.onRequestComplete();
return JSC.JSValue.jsNumberFromInt32(0);
}

View File

@@ -504,10 +504,42 @@ static void writeFetchHeadersToUWSResponse(WebCore::FetchHeaders& headers, uWS::
}
}
auto* data = res->getHttpResponseData();
for (const auto& header : internalHeaders.commonHeaders()) {
const auto& name = WebCore::httpHeaderNameString(header.key);
const auto& value = header.value;
// We have to tell uWS not to automatically insert a TransferEncoding or Date header.
// Otherwise, you get this when using Fastify;
//
// curl http://localhost:3000 --verbose
// * Trying [::1]:3000...
// * Connected to localhost (::1) port 3000
// > GET / HTTP/1.1
// > Host: localhost:3000
// > User-Agent: curl/8.4.0
// > Accept: */*
// >
// < HTTP/1.1 200 OK
// < Content-Type: application/json; charset=utf-8
// < Content-Length: 17
// < Date: Sun, 06 Oct 2024 13:37:01 GMT
// < Transfer-Encoding: chunked
// <
//
if (header.key == WebCore::HTTPHeaderName::ContentLength) {
if (!(data->state & uWS::HttpResponseData<isSSL>::HTTP_END_CALLED)) {
data->state |= uWS::HttpResponseData<isSSL>::HTTP_END_CALLED;
res->writeMark();
}
} else if (header.key == WebCore::HTTPHeaderName::TransferEncoding || header.key == WebCore::HTTPHeaderName::Date) {
if (!(data->state & uWS::HttpResponseData<isSSL>::HTTP_WRITE_CALLED)) {
data->state |= uWS::HttpResponseData<isSSL>::HTTP_WRITE_CALLED;
res->writeMark();
}
}
writeResponseHeader<isSSL>(res, name, value);
}

View File

@@ -1341,10 +1341,13 @@ const ServerResponsePrototype = {
return this;
}
if (!$isCallable(callback) && callback !== undefined) {
callback = undefined;
}
const handle = this[kHandle];
if (handle) {
const headerState = this[headerStateSymbol];
if (headerState !== NodeHTTPHeaderState.sent) {
handle.cork(() => {
handle.writeHead(this.statusCode, this.statusMessage, this[headersSymbol]);
@@ -1354,11 +1357,12 @@ const ServerResponsePrototype = {
this[headerStateSymbol] = NodeHTTPHeaderState.sent;
// https://github.com/nodejs/node/blob/2eff28fb7a93d3f672f80b582f664a7c701569fb/lib/_http_outgoing.js#L987
this._contentLength = handle.end(chunk, encoding, callback);
this._contentLength = handle.end(chunk, encoding);
});
} else {
handle.end(chunk, encoding, callback);
handle.end(chunk, encoding);
}
this.finished = true;
}
return this;
@@ -1384,6 +1388,10 @@ const ServerResponsePrototype = {
let result = 0;
if (!$isCallable(callback)) {
callback = undefined;
}
if (this[headerStateSymbol] !== NodeHTTPHeaderState.sent) {
handle.cork(() => {
handle.writeHead(this.statusCode, this.statusMessage, this[headersSymbol]);
@@ -1407,7 +1415,8 @@ const ServerResponsePrototype = {
return false;
}
this.emit("drain");
if (result > 0) this.emit("drain");
return true;
},