Skip to content

Add a TouchSocket entry (disabled pending a close-path fix) - #1453

Open
MDA2AV wants to merge 1 commit into
mainfrom
touchsocket-entry
Open

Add a TouchSocket entry (disabled pending a close-path fix)#1453
MDA2AV wants to merge 1 commit into
mainfrom
touchsocket-entry

Conversation

@MDA2AV

@MDA2AV MDA2AV commented Sep 5, 2026

Copy link
Copy Markdown
Owner

TouchSocketTouchSocket.Http, the HTTP/1.1 server component of the framework, added as an engine.

Requests are answered from an IHttpPlugin, which is how the library exposes its HTTP pipeline: the plugin sees each request, answers the ones it recognises and passes the rest along. h1 cleartext on :8080, plus the async delay.

Profiles
baseline, pipelined, limited-conn, async, latency-1m, latency-10k, json-comp

Why it is committed disabled

It does not pass validation, and the cause is in the library rather than in the entry, so I would rather land it visibly with a reproduction than quietly drop it.

A request that arrives split across TCP segments and asks for Connection: close is answered with nothing — the socket is closed instead of the response being flushed.

Sweeping every split offset of a single request against TouchSocket.Http 4.3.6 on .NET 10:

request result
Connection: keep-alive 54/54 offsets answered correctly
Connection: close 20/73 offsets answered with nothing

So request reassembly is fine — it is the close path specifically. Ordinary curl traffic never shows it, which is why the entry looks healthy by hand and fails the harness: the fragmentation checks send exactly that shape.

Reproduction

The handler does no parsing of its own, so nothing between the socket and the plugin is this entry's code:

import socket, time
req = b"GET /baseline11?a=13&b=42 HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"
for split in (4, 34, 41):
    s = socket.create_connection(("127.0.0.1", 8080))
    s.sendall(req[:split]); time.sleep(0.01); s.sendall(req[split:])
    print(split, s.recv(4096)[:40])   # b'' on the failing offsets
    s.close()

Flip enabled to true in meta.json once this is fixed and the entry should pass as it stands.

Notes

  • /json is serialized from the parsed model on every request and compressed only when the client asked for it, at brotli quality 1 — nothing answered from a precomputed body.
  • The project is named touchsocketarena rather than touchsocket: a project named for the package it depends on makes NuGet resolve a dependency cycle on itself (NU1108).

@RRQM — flagging you as TouchSocket's maintainer, both so you can see how the library is being represented here and because of the Connection: close behaviour above. Happy to move that to an issue on RRQM/TouchSocket if you would rather track it there, and to re-run the full suite against any fix.

TouchSocket.Http is the HTTP/1.1 server component of the TouchSocket networking
framework. Requests are answered from an IHttpPlugin, which is how the library
exposes its HTTP pipeline: the plugin sees each request, answers the ones it
recognises and passes the rest along. h1 cleartext on :8080, plus the async
delay.

It is committed with enabled: false, because it does not pass validation and the
reason is in the library rather than in the entry.

A request that arrives split across TCP segments AND asks for Connection: close
is answered with nothing - the socket is closed instead of the response being
flushed. Sweeping every split offset of one request:

    Connection: keep-alive    54/54 offsets answered correctly
    Connection: close         20/73 offsets answered with nothing

So request reassembly is fine; it is the close path. Ordinary curl traffic never
shows it, which is why the entry looks healthy by hand and fails the harness -
the fragmentation checks send exactly that shape.

The handler does no parsing of its own, so nothing between the socket and the
plugin is this entry's code. Repro and measurements are in the README.

/json is serialized from the parsed model on every request and compressed only
when the client asked for it, so nothing is answered from a precomputed body.

The project is named touchsocketarena rather than touchsocket: a project named
for the package it depends on makes NuGet resolve a dependency cycle on itself.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant