Skip to content

http: port Go net/http timeout handling#67

Open
Darckfast wants to merge 1 commit into
tinygo-org:mainfrom
Darckfast:port-net-http-timeout
Open

http: port Go net/http timeout handling#67
Darckfast wants to merge 1 commit into
tinygo-org:mainfrom
Darckfast:port-net-http-timeout

Conversation

@Darckfast

@Darckfast Darckfast commented Jul 5, 2026

Copy link
Copy Markdown

This PR ports Go's net/http timeout feature to TinyGo allowing it to handle timeouts when using net/http e.g.

c := http.Client{
  Timeout: 2 * time.Second,
}

^ this will now return a timeout error if the request duration is longer than 2 seconds

This port is pretty much 1:1 to Go own timeout implementation, i removed parts that TInyGo doesnt support (they are commented with // TINYGO)

By bringing the Go net/http client .transport() function, it also fixes the issue where only roundTrip.go was used by default, even when compiling to wasm, where roundTrip_js.go should be used

Fixes #58
Fixes #66

I have wrote a wasm integration test , but i dont know how to go about it because it's inside test/wasm in the main repo, do i just open a PR in the main repo with it? or you guys suggest something else?

This ports Go's timeout feature to TinyGo allowing it to handle timeouts when using `net/http` e.g. `c := http.Client{Timeout: 2 * time.Second}` will now return a timeout error if the request duration is longer than 2 seconds

By bringing the Go net/http client `.transport()` function, it also fixes the issue where only `roundTrip.go` was used, even when compiling to wasm, where `roundTrip_js.go` should be used

Fixes tinygo-org#58 and tinygo-org#66
@Darckfast
Darckfast force-pushed the port-net-http-timeout branch from 146f177 to ba49238 Compare July 12, 2026 01:17
@b0ch3nski

Copy link
Copy Markdown

I have wrote a wasm integration test , but i dont know how to go about it because it's inside test/wasm in the main repo, do i just open a PR in the main repo with it? or you guys suggest something else?

Yes, please do so and maybe change net submodule to your branch so it can be tested together?

@0pcom

0pcom commented Jul 15, 2026

Copy link
Copy Markdown

Tested this against a real workload — the Skycoin daemon and web wallet, which use http.Client{Timeout: …} for peer/node queries — on the native (non-wasm) roundTrip.go path, combined with the host netdev from #59.

Confirmed it fixes the #58 crash: http.Client{Timeout}.Get() to an unreachable host now returns the dial error instead of panicking on the nil didTimeout. 👍

One thing worth flagging for the native path: the Timeout timer fires but doesn't actually abort an in-flight request. Against a server that sleeps 4s with a 1s client timeout, the call returns after the full ~4s with a nil error instead of timing out at ~1s:

T1 refused: true | connection refused        (crash fixed ✓)
T2 slow:   err=<nil> elapsed=4003ms          (want timeout ~1000ms)

setRequestCancel wires up req.Cancel/context and the timer correctly, but http/roundTrip.go (the native approximation of Transport.roundTrip) never observes req.Cancel/context/deadline and nothing sets a read deadline on the conn — so when the timer fires there's nothing to interrupt the read. On the wasm path roundTrip_js.go can cancel via the browser fetch, so this only affects the native path.

Not a blocker for this PR — fixing the crash is already a clear improvement. Just flagging that making Timeout actually cut off a slow response on native will additionally need roundTrip to honor cancellation (close the conn or set a read deadline when req.Cancel fires). Happy to help with that as a follow-up.

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.

net/http: client always uses TinyGo roundTrip instead of roundTrip_js in wasm Tinygo crashes on http.Client{}.Do() with Timeout

3 participants