Skip to content

HTTP/2 103 not requesting linked resources #6202

Closed

Description

@Thyran

I am really struggling with this for two days now and I can not explain why it would not work. Is there anything I am missing with this or does it simply not work?

I have set up a normal express app in nodejs with a http2 secure server and early hints being written:

import fs from "fs";
import path from "path";
import zlib from "zlib";
import http2 from "http2";
import express from "express";
import http2Bridge from "http2-express-bridge";

import { SERVER_ROOT } from "../etc/root";
import { CLIENT_ROOT } from "../etc/root";

const app = http2Bridge(express);

const earlyHints = [
    "</css/index.css>; rel=preload; as=style",

    "</js/index.js>; rel=preload; as=script",
    "</js/theme.js>; rel=preload; as=script"
];

const earlyHintObject = {
    "link": earlyHints
};

app.get("/", function(req, res, next) {
    req.url = "index.html";

    res.writeEarlyHints(earlyHintObject);

    next("route"); // redirection of the path from / to /index.html
});

app.use("/svg", function(req, res, next) {
    res.setHeader("Cache-Control", "public, max-age=3600");
    res.setHeader("Content-Type", "image/svg+xml");

    next();
});

app.use("/templates", function(req, res, next) {
    res.setHeader("Cache-Control", "private, max-age=3600, must-revalidate");
    next();
});

app.use(function(req, res) {
    res.setHeader("Content-Encoding", "gzip");

    fs.createReadStream(path.join(CLIENT_ROOT, req.baseUrl, req.path))
        .pipe(zlib.createGzip())
        .pipe(res);
});

const appPort = process.env.APP_PORT || 443;

const httpsKey = fs.readFileSync(process.env.HTTPS_KEY_FILE || path.join(SERVER_ROOT, "ssl", "https.key"));
const httpsCertificate = fs.readFileSync(process.env.HTTPS_CRT_FILE || path.join(SERVER_ROOT, "ssl", "https.crt"));

const httpsOptions: http2.SecureServerOptions = {
    key: httpsKey,
    cert: httpsCertificate,

    allowHTTP1: true
};

// set up http server for ui access
const appServer = http2.createSecureServer(httpsOptions, app);
appServer.listen(appPort, function() {
    console.log("Web server listening on port " + appPort);
});

Currently I am streaming the requested resources via a gzip stream, but that does not change the problem in any way as I have tested.

When I open the page in the browser I get the early hints presented to me separate from the response headers as it should be, but then nothing happens with them.

I also tried using a timeout to artificially extend the response time, which also gave the desired effect of defering the response while the early hints were transmitted instantly.

However nothing is done with them. All it does is wait for the response body and nothing is requested.
Output from curl -X GET https://localhost -kvs --http2

*   Trying 127.0.0.1:443...
* Connected to localhost (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1

... (TLS handshake)

> GET / HTTP/2
> Host: localhost
> user-agent: curl/7.81.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 103
< link: </css/index.css>; rel=preload; as=style, </js/index.js>; rel=preload; as=script, </js/theme.js>; rel=preload; as=script

(long pause here when using a timeout)

* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< x-powered-by: Express with http2-express-bridge
< content-encoding: gzip
< date: Tue, 03 Dec 2024 16:00:18 GMT
<
* Failure writing output to destination
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* stopped the pause stream!
* Connection #0 to host localhost left intact

I really don't see what could be missing and more specific information is really hard to get, so I hope maybe other pairs of eyes can spot something.

Activity

  1. converted this issue into a discussion #6203 on Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions