Observing HTTP 103 Early Hints on localhost: Verifying the difference from 200 using Node.js and curl

ネットワーク・RFCカテゴリを表すパンダのイラスト Networking / RFC

About this article
This article was created using an automated generation workflow powered by generative AI. We verified the specifications of RFC 8297 and Node.js writeEarlyHints, and set up an experiment on localhost to distinguish between informational and final responses. This has not been executed in a target environment.

Verification Status: 📘 RFC and official Node.js documentation verified / Actual hardware unverified

HTTP statuses are not limited to 200 and 404.103 Early Hintsis an informational response that informs the browser of resource loading candidates before the server returns the final response such as HTML. Seeing 103 alone does not indicate whether the site terminated successfully.

We will observe this difference on localhost. With Node.js 18.11 or later and curl, you can try this without using external sites.

Roles of HTTP 103 and 200

クライアント         サーバー
GET /       -------->
           <-------- 103 Early Hints
                     Link: </style.css>; rel=preload
           <-------- 200 OK
                     最終HTML

RFC 8297 defines 103 as aninformational responseLoading "hints" serve as material for preliminary preparation by the client. They do not replace the meaning of the final 200 or 500.

StatusPrimary RoleUsed for Success Determination?
103 Early HintsEarly clues such as LinkNot used independently
200 OKNormal final responseDetermine along with the response content
404 Not FoundTarget not foundConfirm as the final result
500 Internal Server ErrorServer-side anomalyTreat as an error

Try running it

early-hints-local.jsCreate a file named.

const http = require("node:http");

const server = http.createServer((req, res) => {
  if (req.url === "/style.css") {
    res.writeHead(200, { "content-type": "text/css" });
    res.end("body { color: navy; }");
    return;
  }
  if (req.url !== "/") {
    res.writeHead(404);
    res.end("not found");
    return;
  }

  // 最終応答の準備が終わる前にLinkヒントを送る
  res.writeEarlyHints({
    link: "</style.css>; rel=preload; as=style"
  });
  setTimeout(() => {
    res.writeHead(200, {
      "content-type": "text/html; charset=utf-8",
      link: "</style.css>; rel=preload; as=style"
    });
    res.end("<!doctype html><h1>hello</h1>");
  }, 700);
});

server.listen(30031, "127.0.0.1", () => {
  console.log("http://127.0.0.1:30031/");
});

127.0.0.1Since it listens only on, it is not exposed externally. If port 30031 conflicts with another process, please change the number.

Start the server on Terminal A and use curl on Terminal B.

node early-hints-local.js
curl --http1.1 --include --no-progress-meter \
  http://127.0.0.1:30031/

This is the expected response sequence (not actual device output).

HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
<!doctype html><h1>hello</h1>

Press Ctrl+C to terminate the server. When launching Node.jsEADDRINUSEappears, another program is using the same port. Instead of stopping the existing service, change the sample-side port.

Daily-Code-Samples: Local experiment with HTTP 103The executable version and explanation have been placed in.

Change one location and observe

res.writeEarlyHints(...)Comment out the line, restart, and run the same curl. This time, 103 should be absent, leaving only the final 200.

// res.writeEarlyHints({
//   link: "</style.css>; rel=preload; as=style"
// });

This confirms that 103 and 200 are independent. Furthermore, on localhostres.writeHead(500)to , you can reproduce the case where 103 returns first but results in an error later.

The Meaning and Limitations of the Link Header

</style.css>; rel=preload; as=styleEach part of indicates the URL of the preload candidate, the relationship (preload), and its handling as a stylesheet. However, browsers do not always prefetch resources. The appearance of headers in curl is also not proof that the CSS has been downloaded.

Whether resources are actually fetched earlier should be verified using the Network tab in browser developer tools or performance measurements. The prerequisites also change if caching is enabled.

Precautions for Production Use

Proxies/CDNs and older HTTP/1.1 clients may not handle informational responses as expected. RFC 8297 contains security considerations regarding the interoperability of informational responses.

Additionally, in HTTP monitoring processes, it is important not to treat the initially observed 103 as "response complete".Receipt of 103, a final status of 200, and confirmation that prefetching actually occurredare recorded separately.

When using this on a production site, verify the correct Link destination, the actual final response, client compatibility, and the impact on load in order. Do not assume performance improvements without actual measurements before and after deployment.

Official Documentation

Document information

Article title
Observing HTTP 103 Early Hints on localhost: Verifying the difference from 200 using Node.js and curl
Published
Updated
Source
https://papanda925.com/?p=18082&lang=en

License: Text and original figures for which this site holds the relevant rights are available under CC BY 4.0 , unless otherwise noted. This article may include content created or edited with generative AI. If code has a separate license notice or a linked GitHub repository license, that license takes precedence for the code. Quotations, third-party materials, images, and trademarks are excluded from this license. Usage policy

Copied title and URL