Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: send 103 Early Hints responses #95

Merged
merged 6 commits into from
Oct 16, 2023
Merged

Conversation

chalasr
Copy link
Contributor

@chalasr chalasr commented Oct 18, 2022

This makes Vulcain sends 103 Early Hints responses when server-push isn't supported (with preload links).
The patch might be very naive but here we are, first contrib in Go. Please tell me if there is something else to be done.

@CLAassistant
Copy link

CLAassistant commented Oct 18, 2022

CLA assistant check
All committers have signed the CLA.

@chalasr chalasr changed the title feat: send 103 Early Hints responses along preload links feat: send 103 Early Hints responses Oct 19, 2022
@andrerom
Copy link
Contributor

There is a todo comment about early hints on line 251, can it be removed now or more changes needed?

@chalasr
Copy link
Contributor Author

chalasr commented Oct 21, 2022

Todo removed, thanks @andrerom.
Also I just added a test, sadly it's failing: The 103 response is sent as expected, but it does not have the Link headers. I must be missing something as that header should be forwarded to the 103 response before it is sent. Any idea?

@@ -227,6 +227,7 @@ func (v *Vulcain) Apply(req *http.Request, rw http.ResponseWriter, responseBody
}
if addPreloadToVary {
responseHeaders.Add("Vary", "Preload")
rw.WriteHeader(http.StatusEarlyHints)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that it's the good place to send the 103 response (hence the test failure).

This should be done here:

v.addPreloadHeader(newHeaders, url)

and here:

v.addPreloadHeader(newHeaders, url)

Maybe should we refactor the code to prevent sending many 103 responses and send it only when all Preload headers have been computed?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think that Server Push should now be opt-in (through a config option). By default, we should only use 103 responses as they are the new standard. This can be done in another PR of course.

Copy link
Contributor Author

@chalasr chalasr Oct 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I had to gather preload links added by push() and manually add them to the ResponseWriter header map as they were not for some reason. With this approach, only one 103 response is sent with all Links included.
The code feels a bit hackish but it works as expected so unless you see door for improvement, this is ready to go on my side.

@chalasr chalasr force-pushed the 103-early-hints branch 11 times, most recently from a1c53af to 4d78bc0 Compare October 23, 2022 15:17
vulcain.go Outdated
}
rw.WriteHeader(http.StatusEarlyHints)
// remove extra Link from final response headers
rw.Header().Del("Link")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Contributor Author

@chalasr chalasr Oct 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this, the final response ends up with an extra - duplicated preload link. If you want to try it out (would be nice): checkout my PR, comment that line and run go test -v -timeout 30s -run PreloadHeader

@chalasr chalasr force-pushed the 103-early-hints branch 2 times, most recently from ac8b0ca to 90bbeb3 Compare October 23, 2022 21:22
@chalasr
Copy link
Contributor Author

chalasr commented Nov 1, 2022

Also, I think that Server Push should now be opt-in (through a config option). By default, we should only use 103 responses as they are the new standard. This can be done in another PR of course.

Work ongoing in https://github.com/dunglas/vulcain/compare/main...chalasr:vulcain:firstclass-103?expand=1
It'd be great to get this PR resolved/merged first as the WIP depends on it.

@pautier
Copy link

pautier commented Nov 7, 2022

Also, I think that Server Push should now be opt-in (through a config option). By default, we should only use 103 responses as they are the new standard. This can be done in another PR of course.

Work ongoing in https://github.com/dunglas/vulcain/compare/main...chalasr:vulcain:firstclass-103?expand=1 It'd be great to get this PR resolved/merged first as the WIP depends on it.

Hi guys do you think we can move forward with the @chalasr PR, we need it to use correctly VULCAIN :(

vulcain.go Outdated
}
rw.WriteHeader(http.StatusEarlyHints)
// remove extra Link from final response headers
rw.Header().Del("Link")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? I'm not sure to well understand what's going on here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#95 (comment)

Without this, the final response ends up with an extra - duplicated preload link. If you want to try it out (would be nice): checkout my PR, comment that line and run go test -v -timeout 30s -run PreloadHeader

Btw, should the final response actually have links if we already sent them in a 103?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it even must have them, or downloaded data will be discarded.

@chalasr
Copy link
Contributor Author

chalasr commented Dec 10, 2022

Friendly ping :)

@dunglas
Copy link
Owner

dunglas commented Jan 17, 2023

I pushed a commit simplifying bit the code. I tested locally with Caddy, and it works as expected, the test failure is because the legacy proxy doesn't seem to support 103 properly and is still used by the test suite.

@chalasr chalasr force-pushed the 103-early-hints branch 2 times, most recently from 2a810b0 to 07bb98d Compare February 5, 2023 15:51
@dunglas
Copy link
Owner

dunglas commented Feb 8, 2023

Now that Go 1.20 is released, it should be possible (I hope), to add proper support for 103 Early Hints to the legacy server that we use in our tests suite using a director function: https://pkg.go.dev/net/http/httputil#ReverseProxy.Director

We'll have to keep supporting Go 1.19 until caddyserver/caddy#5288 is fixed.

Another option would be to add a test for this feature in the Caddy module now that caddyserver/caddy#5187 is merged (we should be able to re-enable the tests for the Caddy module of Mercure by the way, but that's not related to this project 😅).

Even if we follow this path, I would like that we add an example using a director function, at least because it will be displayed in the docs and we want to keep good examples of how to use Vulcain as a library without Caddy.

WDYT?

@chalasr
Copy link
Contributor Author

chalasr commented Feb 24, 2023

Works for me, I can be back on this PR in March. Sorry for the late reply

@dunglas
Copy link
Owner

dunglas commented Aug 3, 2023

Caddy 2.7 is out. We can now drop support for Go 1.19!

@dunglas
Copy link
Owner

dunglas commented Oct 16, 2023

Thanks @chalasr. I fixed a tricky issue and some flaky tests. It's entirely green now 🎉

@dunglas dunglas merged commit 6329c52 into dunglas:main Oct 16, 2023
6 checks passed
@chalasr chalasr deleted the 103-early-hints branch October 16, 2023 14:25
@chalasr
Copy link
Contributor Author

chalasr commented Oct 16, 2023

Thank you!

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.

None yet

5 participants