Commit Graph
389 Commits
Author SHA1 Message Date
muki 57b86112b3 Merge pull request #3240 from lightpanda-io/xhr-async-flag
XHR Sync Request
2026-08-26 17:11:48 -07:00
Karl Seguin fce38a1aa8 Merge pull request #3289 from lightpanda-io/fix-double-releases
fix: Fix double-release and other (edge-case) memory issues
2026-08-27 07:34:45 +08:00
Karl Seguin cfd921ecab fix: Fix double-release and other (edge-case) memory issues
Our `Arena` from the `ArenaPool` now tracks if it's already been released. On
a subsequent release, it panics then and there. Without this, the code will
almost certainly panic anyways, but it will panic in a seemingly unrelated
place. Hopefully this makes identifying future cases of this easier (since we'll
get the stack trace of the re-releaser).

Fix 3 separate memory issues, all edge cases.

1 - an XHR error handler that re-open/sends would incorrectly null the new
    transfer (maybe this isn't that odd, maybe it's a common retry-on-error).

2 - On a curl_easy_pause error (from WebSocket.zig) we now unqueue the just-
    queued message, because the error will errdefer the message arena to be
    cleaned up.

3 - ScriptManager now cleans up after itself on a failure prior to submit()
    being called.
2026-08-26 18:24:12 +08:00
Pierre Tachoire 467167d6e6 http: strip Authorization on cross-origin redirects 2026-08-26 10:00:11 +02:00
Muki Kiboigo 234d47d0e2 syncRequest -> submitSync on Transfer 2026-08-25 17:43:03 -07:00
Halil Durak 87a87ba62e HttpClient: remove pending_low_queue, separate keys for headers_only in cache, more eager connection reuse 2026-08-25 14:20:38 +03:00
Halil Durak c1079444c4 addHeader -> setHeader + enable low prio for images 2026-08-25 14:18:46 +03:00
Halil Durak e58f99da18 add --load-resources CLI arg, supporting image param 2026-08-25 14:18:45 +03:00
Karl Seguin 99ee50259b Merge pull request #3248 from lightpanda-io/transfer-single-outcome-guarantee
http: Guarantee Transfer contract of single outcome callback
2026-08-25 07:08:54 +08:00
Karl Seguin a6618fff63 http: Guarantee Transfer contract of single outcome callback
HttpClient guarantees that only one of done/error/shtudown callback will be
called. But that guarantee had a hole when a done/error callback would trigger
JS that caused an HttpClient.abort (e.g. by scheduling a navigation).

So far, this isn't a problem. fetch/XHR guard against this themselves, and
ScriptManager doesn't care of it happens.

But https://github.com/lightpanda-io/browser/pull/3230 doesn't guard against it
and would crash if it happens: its doneCallback frees `self` but can re-enter
shutdown which needs `self`. While 3230 could fix this issue, I'd prefer to
bake this contract into the HttpClient. Transfers now have an
`_outcome_delivered: bool` which guarantees that only one of done/error/shutdown
is called.
2026-08-22 11:09:52 +08:00
Karl Seguin 2d32e78838 chore: Remove Server component from Network
Network is less cohesive than https://github.com/lightpanda-io/browser/pull/3242
would indicate. It has two distinct and _completely_ separate responsibilities.

1 - It acts as the base for each HttpClient, providing a shared connection pool
    (for http and ws) and access to the process wide Cache, RobotStore,
    WebBothAuth, certificates, ...

2 - It accepts, polls and reads from CDP connection

There is zero relationship between these, and it's a particularly bad place for
this duality to exist because both parts are, in their own way, the main
multi-threaded junction in the system.

This commit is purely mechanical it:

1 - Keeps network as the base for each HttpClient.
2 - Extract the CDP interaction into the existing Server.zig
3 - Gives mcp's HttpServer its own accept loop
2026-08-22 10:11:30 +08:00
Karl Seguin 46d53792b8 chore: Network cleanup
Network has accumulated a bit of bagged. It knows a lot about certificates, it
knows a lot of the cache. I have plans to expand Network, and wanted to clean it
up.

1 - certificate logic moved to dedicated Certificates.zig
2 - Removed CurlDebugAllocator
    - this makes setup easier, to Updater can just init libcurl directly
3 - Change Updater to be a single function
4 - Cache initialization is don in the Cache
5 - ?Cache => Cache{.kind = .noop}
2026-08-22 09:21:18 +08:00
Karl Seguin 57bcdfed10 chore: Simplify Network and HttpClient init
Remove app field from Network
2026-08-22 07:05:05 +08:00
Karl Seguin decedca6e7 chore: Network cleanup
Network has accumulated a bit of bagged. It knows a lot about certificates, it
knows a lot of the cache. I have plans to expand Network, and wanted to clean it
up.

1 - certificate logic moved to dedicated Certificates.zig
2 - Removed CurlDebugAllocator
    - this makes setup easier, to Updater can just init libcurl directly
3 - Change Updater to be a single function
4 - Cache initialization is don in the Cache
5 - ?Cache => Cache{.kind = .noop}
2026-08-22 07:04:58 +08:00
Karl Seguin 9f4b39d723 Merge pull request #3239 from lightpanda-io/ratelimiter
http: Add optional rate limit
2026-08-22 06:58:52 +08:00
Karl Seguin 09edfd3ce5 http: Add optional rate limit
Add an optional per-host rate limit. This currently only applies to the top-
level navigation. This makes it simpler to implement and simpler to reason
about. The full load of a page is only ever delayed at its head, not
sporadically through the page loading.

The use-case where a RateLimiter is most useful is when the browser is crawling
multiple pages of the same site, and in that case, the top-level rate limit
still applies some degree of limit to any linked resources (e.g. a JS on a
different host).

`--http-nav-delay` is the delay, in milliseconds, to apply to top level
navigates per host. Currently defaults to 0 (disabled).

`--http-nav-burst` is the burst allowed per host. Defaults to 1 (has no impact
when `--http-nav-delay` is disabled).
2026-08-20 16:03:42 +08:00
Karl Seguin b70f7a325e webapi: Blob / File conformance
1-
Per spec, dictionary objects should be loaded in lexicographical order (a). So
the following always pushes `endings` before `type`

```js
  new Blob([], {
    get type()    { order.push('type'); return ''; },
    get endings() { order.push('endings'); return 'transparent'; },
  });
```

This requirement is now enforced by a comptime check. So, a lot of files were
updated to satisfy this requirement.

2-
Blob parts now work with the @@iterator protocol. This is done more generically
(via `value.iterator())` but is currently only used by Blob (and File). Other
types that need this (e.g. URLSearchParams) can be done in a follow up.

3-
Add support for Blob.textStream

4-
Reject XHR/Fetch requests on blob URLs if the method isn't GET

5-
Strip #hash from blob URL when doing lookup

All of this fixes ~175 FileAPI WPT cases, though it's possible #1 (the
dictionary ordering) helps with a few others.

(a) https://webidl.spec.whatwg.org/#js-dictionary
2026-08-20 13:57:51 +08:00
Pierre Tachoire 067709bb58 cdp: add obeyRobots to lp.configureCDP 2026-08-18 17:07:18 +02:00
Karl Seguin d3c26f589e Merge pull request #3219 from lightpanda-io/sec-ch-ua-full-version
send Sec-Ch-Ua-Full-Version-List header
2026-08-18 20:00:44 +08:00
Pierre Tachoire 9ff1ad8306 fix header key case for Sec-Ch-Ua* 2026-08-18 12:25:40 +02:00
Pierre Tachoire a961156283 send Sec-Ch-Ua-Full-Version-List header
Add Sec-Ch-Ua-Full-Version-List header with the full LP version

```
Sec-Ch-Ua-Full-Version-List: "Lightpanda";v="1.0.0-dev.8713+33867c727"
```
2026-08-18 09:38:00 +02:00
Karl Seguin 5c0aa90ea4 Merge pull request #3187 from lightpanda-io/http-header-option
add --http-header option to send headers on every HTTP requests
2026-08-18 15:24:10 +08:00
Pierre Tachoire 33867c7275 Merge pull request #3116 from lightpanda-io/nikneym/adblocker-init
Initial implementation for easy list parsing and AdBlocker
2026-08-18 08:50:42 +02:00
Karl Seguin a9b96fe5f8 Centralize header validation
Mime.isHttpToken already exists for the header name, added
Mime.isHttpHeaderValue which was extracted from het/Headers.zig. Now Config (
for validating CLI headers), net/Headers for script headers, and cdp/network.zig
all use the same validation methods.
2026-08-18 13:02:15 +08:00
Pierre Tachoire a6afdce444 add --http-header option to send headers on every HTTP requests 2026-08-17 17:18:13 +02:00
Pierre Tachoire 366f889c29 Merge pull request #3201 from lightpanda-io/robots-allowed-disallowed
`robots.txt` status handling
2026-08-17 11:54:27 +02:00
Muki Kiboigo 3bebe80e2f 401 and 403 are treated as disallow by RobotsGate 2026-08-15 11:48:06 -07:00
Pierre Tachoire 5b0835f5a1 Merge pull request #3203 from lightpanda-io/enforce-ua-restriction-rework
http: improve header overwrite/enforcement
2026-08-15 07:55:34 +02:00
Pierre Tachoire ad072b2074 Merge pull request #3200 from lightpanda-io/enforce-ua-restriction
Enforce User-Agent and Sec-Ch-Ua HTTP headers restriction
2026-08-15 07:55:27 +02:00
Karl Seguin 737f69ee44 http: improve header overwrite/enforcement
Builds ontop of https://github.com/lightpanda-io/browser/pull/3200 to centralize
header enforcement and standardize merge vs overwrite header logic.

The API is still a `setHeader` and `appendHeader`, with a source, but set/append
both are thin wrappers around private `putHeader`. putHeader blocks overwriting
restricted headers (user-agent). The `source` acts as a priority (ordered enum)
which further restricts the header AND depending on whether set or append were
called, controls if the value is overwritten or appended to.

3200 had an always-append which can cause problems, e.g. a script setting
Accept-Language: fr would have results in the value being appended to the
default, e.g.: 'en-US,en;q=0.9, fr'.
2026-08-15 12:09:08 +08:00
Muki Kiboigo 7cb6590642 better handling of allowed and disallowed robots cases 2026-08-14 08:52:37 -07:00
Pierre Tachoire dd83300095 htttp: add Transfer.appendHeader
and make transfer.addHeader private.
2026-08-14 16:33:49 +02:00
Pierre Tachoire 6e72441001 make Sec-Ch-Ua not modifiable via cdp 2026-08-14 16:05:19 +02:00
Pierre Tachoire 80e45ab016 apply user-agent validation rules on request intercepted 2026-08-14 12:26:33 +02:00
Karl Seguin a3034105aa chore: Move cache maintenance to startup and browser.deinit
--http-cache-entry-limit is currently implemented as a hard-limit via a check
on every put. For a large --http-cache-entry-limit, this can result in a non-
trivial delay on every http get.

This commit calls cache.maintenance() on Browser.deinit and on startup.
maintenance:
1 - purges stale entries
2 - enforces the limit

With concurrent requests, the number of entries can easily exceed the limit by
hundreds of entries (but this is temporary).
2026-08-14 15:55:37 +08:00
Pierre Tachoire 92e3cfcbe9 fix errdefer path on singleflight 2026-08-13 17:55:48 +02:00
Muki Kiboigo a356840c63 remove from pending on waiting append error in SingleFlight 2026-08-13 08:25:18 -07:00
Muki Kiboigo fb5a9b6a35 get rid of allocator stored in RobotsGate 2026-08-13 08:20:15 -07:00
Muki Kiboigo 21856170e3 single lookup for SingleFlight pending 2026-08-13 08:20:14 -07:00
Halil Durak 90adef8c92 HostnameTrie: update doc-comment 2026-08-13 16:54:39 +03:00
Halil Durak 48282a9307 Parser: count the rule lines it drops 2026-08-13 16:39:17 +03:00
Halil Durak a481cd7c40 update tests 2026-08-13 16:39:16 +03:00
Halil Durak 971b758f29 Network: changes after relocation of fromConfig 2026-08-13 16:39:16 +03:00
Halil Durak c4b0b7cc33 HttpClient: check the adblocker inside isUrlBlocked` 2026-08-13 16:39:16 +03:00
Halil Durak 493065e348 Parser: update test 2026-08-13 16:39:16 +03:00
Halil Durak d8de3b0dd4 AdBlocker: change how we count skipped 2026-08-13 16:39:15 +03:00
Halil Durak 4845a98b1f NetworkFilter: drop dead pattern field, reduce $domain= to a bool 2026-08-13 16:39:15 +03:00
Halil Durak 168ed8157b domain: introduce validate and remove parse fn + dead code 2026-08-13 16:39:15 +03:00
Halil Durak 6f76f8053f AdBlocker: update tests 2026-08-13 16:39:15 +03:00
Halil Durak 60cd7e63db AdBlocker: tracking of rules_loaded and rules_skipped
Also moves `fromConfig` and `loadList` to here.
2026-08-13 16:39:14 +03:00