Skip to content

[refactor] add Progressive HEAD simulation & Stream utility functions#19

Merged
TechQuery merged 10 commits intomasterfrom
copilot/simulate-head-request-support
Mar 24, 2026
Merged

[refactor] add Progressive HEAD simulation & Stream utility functions#19
TechQuery merged 10 commits intomasterfrom
copilot/simulate-head-request-support

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 7, 2026

PR-19 PR-19 PR-19 Powered by Pull Request Badge

HTTPClient.head() previously threw when a server didn't support HEAD. This adds a three-tier fallback chain to simulate HEAD using minimal bandwidth.

Fallback chain

All three tiers use fetch() directly and are encapsulated entirely inside requestHead(), which is called from within the exported request() function:

  1. HEAD via fetch() — standard fetch() HEAD request; return on success
  2. Range GETGET with Range: bytes=0-4099 (magic number size per file-type); returns headers (including Content-Range) and the first 4100 bytes as an ArrayBuffer
  3. Plain GET via fetch() — reads exactly the first 4100 bytes from the response body using an async generator (for await...of + slice at limit + Array.fromAsync()) then cancels the stream; bytes returned in body
// Servers that reject HEAD and Range will still resolve headers:
const headers = await client.head('https://example.com/file.zip');
// Content-Type, Content-Length, etc. available without downloading the file

Changes

  • source/HTTPRequest.tsrequestHead(req) encapsulates the full three-tier chain; all tiers use fetch() directly (no baseRequest parameter); exports FILE_TYPE_MAGIC_NUMBER_SIZE = 4100 constant and HeadResponse interface ({ headers, body?: ArrayBuffer }); the exported request() function wraps rawRequest (XHR/fetch) and for HEAD requests delegates to requestHead(), returning a synthetic Response{status:204}; non-HEAD requests pass through to rawRequest unchanged
  • source/utility.ts — exports takeBytes(stream, limit) async generator accepting ReadableStream<Uint8Array> directly; reads chunks via for await...of, yields each (slicing the final chunk to honour the limit exactly), and breaks once limit bytes have been produced; the as unknown cast is internal so callers need no type assertions; exports readBytes(stream, limit) that collects the result via Array.fromAsync() into an ArrayBuffer; used by requestHead() for tier 3
  • source/HTTPClient.tshead() is a plain this.request() wrapper going through the normal middleware chain; HEAD simulation is transparent at the request() layer; defaultWare is a simple throw for status > 299 with no HEAD special case
  • test/XMLHttpRequest.ts — simplified mock: dead HEAD→405 special case removed (XHR is no longer called for HEAD)
  • test/Request-Client.spec.ts — four tests covering all three fallback tiers and the request() wrapper; Range GET mock includes Content-Range response header; requestHead() calls omit method; expected synthetic status is 204
  • test/utility.spec.ts — four tests for takeBytes and readBytes using new Blob([...]).stream() for stream creation (no manual makeStream helper); tests verify exact byte-count behaviour and unlimited collection; no as/unknown/any casts at call sites
  • package.json — parcel updated to ^2.16.4 to fix a pre-existing Node.js v24 worker thread crash in the build step

Human changes

  1. [add] Readable Stream utility functions (resolve HTTPClient 支持模拟 HEAD 请求 #18)
  2. [migrate] upgrade to Node.js 24, PNPM 10, JSDOM 29, Cross Env 10, Lint Staged 16 & other latest Upstream packages/actions
  3. [optimize] simplify Copilot codes

📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

Co-authored-by: TechQuery <19969570+TechQuery@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for simulating HEAD requests in HTTPClient feat: HTTPClient.head() with progressive HEAD simulation fallback Mar 7, 2026
…t Staged 16 & other latest Upstream packages/actions

[optimize] simplify Copilot codes
Comment thread source/HTTPClient.ts Outdated
Comment thread source/HTTPClient.ts Outdated
…nto defaultWare

Co-authored-by: TechQuery <19969570+TechQuery@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 8, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • jsonplaceholder.typicode.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/KoAJAX/KoAJAX/node_modules/.bin/jest --detectOpenHandles (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Comment thread source/HTTPRequest.ts Outdated
Comment thread source/HTTPRequest.ts
…bytes before cancel

Co-authored-by: TechQuery <19969570+TechQuery@users.noreply.github.com>
Comment thread source/HTTPClient.ts Outdated
Comment thread source/HTTPRequest.ts Outdated
Comment thread source/HTTPRequest.ts Outdated
…uest for HEAD; head() uses this.request()

Co-authored-by: TechQuery <19969570+TechQuery@users.noreply.github.com>
[optimize] simplify Copilot codes
Comment thread test/Client.spec.ts Outdated
Comment thread source/utility.ts
…ytes/readBytes tests to utility.spec.ts

Co-authored-by: TechQuery <19969570+TechQuery@users.noreply.github.com>
@TechQuery TechQuery marked this pull request as ready for review March 8, 2026 11:20
Comment thread test/utility.spec.ts Outdated
Comment thread test/utility.spec.ts Outdated
Comment thread test/utility.spec.ts Outdated
Comment thread test/Request-Client.spec.ts Outdated
Comment thread test/Request-Client.spec.ts Outdated
Comment thread test/Request-Client.spec.ts Outdated
@TechQuery TechQuery added the feature New feature or request label Mar 22, 2026
Copilot AI requested a review from TechQuery March 22, 2026 07:42
[optimize] upgrade to JSDOM 29 & other latest Upstream packages
[optimize] move Stream Utility tests to independent file
[fix] some Copilot bugs
@TechQuery TechQuery added the enhancement Some improvements label Mar 24, 2026
@TechQuery TechQuery changed the title feat: HTTPClient.head() with progressive HEAD simulation fallback [refactor] add Progressive HEAD simulation & Stream utility functions Mar 24, 2026
@TechQuery TechQuery merged commit 32f2700 into master Mar 24, 2026
@TechQuery TechQuery deleted the copilot/simulate-head-request-support branch March 24, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Some improvements feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTPClient 支持模拟 HEAD 请求

2 participants