-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
Add sse support #527
Add sse support #527
Conversation
Signed-off-by: Emile Vauge <[email protected]>
5f611c7
to
ef637b4
Compare
Hey @emilevauge thanks for all your work on Traefik. It's been really useful for us. Looking at containous/oxy@98f8b7d it looks like your approach here is to treat the First of all, it looks like you are splitting events on But what I really want to ask is if maybe there is a more general solution to this problem? The underlying problem seems to be that Go's As far as I can see, there are 2 ways that buffering could be disabled:
Anyway, just my thoughts. Thanks again for the great project. |
Hi @JayH5
Any help on both 1/ and 2/ is welcomed :) /cc @containous/traefik |
@emilevauge: Thanks for the response. I wasn't aware of the golang stdlib reverse proxy (again, really not a golang expert). Seems strange to me to have a timer-based flushing system 😕. But there's some code in there that nearly gets at what I think could work. I wasn't suggesting writing and flushing data byte-by-byte. But it should be possible to read as much as is available into a buffer and then write and flush. From what I can see, oxy uses It looks like The simplest way I can see to do this would be to just flush the Writer after each buffer is written to it. Copying code from the stdlib reverse proxy it may be possible to do something like this, where the call oxy makes to func (f *httpForwarder) copyBody(dst io.Writer, src io.Reader) {
if f.flush { // Or check for header
if wf, ok := dst.(writeFlusher); ok {
fw := &flushWriter{
dst: wf,
}
dst = fw
}
}
return io.Copy(dst, src)
}
type writeFlusher interface {
io.Writer
http.Flusher
}
type flushWriter struct {
dst writeFlusher
}
func (m *flushWriter) Write(p []byte) (int, error) {
written, err := m.dst.Write(p)
m.dst.Flush()
return written, err
} (This is the most golang I've ever written so there are probably issues with the above). |
@JayH5: I made some changes in oxy to stream the body without analyzing it: containous/oxy@d12fc74 |
dd005fa
to
e9c12a7
Compare
serverEntryPoint.httpServer.BlockingClose() | ||
for serverEntryPointName, serverEntryPoint := range server.serverEntryPoints { | ||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(server.globalConfiguration.GraceTimeOut)*time.Second) | ||
go func(ctx context.Context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, why passing ctx
if you don't use it ? 👼
The less changes for 1.0.1, the better 😉 |
@emilevauge: I've done a bit more digging in the go source code.. and .. it's kind of tricky. I don't think containous/oxy@d12fc74 is going to work. I would still suggest my route of wrapping all calls to |
@JayH5 :
The previous solution was working well in my tests ;) But I agree we could make it better using a wrapper. Here is what I propose. I created a wrapper
The
I will add a unit test in oxy for that use case. BUT, some work will have to be done on this project because the existing tests are not all passing :'( I forked it since the original project is not really maintained anymore but I didn't had time to correct each existing test yet. If you can give some help on this, it would be really appreciated ;) WDYT? |
Signed-off-by: Emile Vauge <[email protected]>
Signed-off-by: Emile Vauge <[email protected]>
Signed-off-by: Emile Vauge <[email protected]>
Signed-off-by: Emile Vauge <[email protected]>
e9c12a7
to
d1b5cf9
Compare
I updated |
@emilevauge sorry I meant to reply but then got distracted trying to get the oxy tests to work. I tried but I think I'm going to give up.. all those chunked-encoding tests are broken and they're not straightforward to fix. It might almost be easier just to pull out the bits of oxy that Traefik uses and start from scratch. The flushing code is looking better. There are a couple of places where I think it could be cleaned up a bit but otherwise it LGTM. Thanks. |
@JayH5 thanks for your help in this :) |
LGTM 👼 |
Signed-off-by: Emile Vauge <[email protected]>
7d90233
to
2d759df
Compare
LGTM |
❤️ |
@emilevauge: in practice, I found the check for the |
This PR adds SSE support.
Fixes #503
Fixes #524