Skip to content

Conversation

@aldas
Copy link
Contributor

@aldas aldas commented Apr 15, 2024

Relates to #1172

Use httputil.ReverseProxy to proxy SSE requests as it has support for streaming responses. See:
https://github.com/golang/go/blob/b107d95b9a66bfe7150fd4f2915e9bb876a6999a/src/net/http/httputil/reverseproxy.go#L601


can be tested with

  1. create separate package and execute this code to start serving proxy application at port 8080 that proxies requests to localhost:8081
package main import ( "errors" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "log" "net/http" "net/url" ) func main() { e := echo.New() e.Use(middleware.Logger()) e.Use(middleware.Recover()) tmpURL, err := url.Parse("http://localhost:8081") if err != nil { log.Fatal(err)	} e.Use(middleware.Proxy(middleware.NewRoundRobinBalancer([]*middleware.ProxyTarget{{URL: tmpURL}}))) if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Fatal(err)	} }
  1. Create application for serving SSE

Go file for application

package main import ( "bytes" "errors" "fmt" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "log" "net/http" "time" ) func main() { e := echo.New() e.Use(middleware.Logger()) e.Use(middleware.Recover()) e.File("/", "./index.html") e.GET("/sse", func(c echo.Context) error { log.Printf("SSE client connected, ip: %v", c.RealIP()) w := c.Response() w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() for { select { case <-c.Request().Context().Done(): log.Printf("SSE client disconnected, ip: %v", c.RealIP()) return nil case <-ticker.C: event := Event{ Data: []byte("ping: " + time.Now().Format(time.RFC3339Nano)),	} if err := event.WriteTo(w); err != nil { return err	} w.Flush()	}	}	}) if err := e.Start(":8081"); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Fatal(err)	} } // Event structure is defined here: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format type Event struct { ID []byte Data []byte Event []byte Retry []byte Comment []byte } // WriteTo writes Event to given ResponseWriter func (ev *Event) WriteTo(w http.ResponseWriter) error { // Marshalling part is taken from: https://github.com/r3labs/sse/blob/c6d5381ee3ca63828b321c16baa008fd6c0b4564/http.go#L16 if len(ev.Data) == 0 && len(ev.Comment) == 0 { return nil	} if len(ev.Data) > 0 { if _, err := fmt.Fprintf(w, "id: %s\n", ev.ID); err != nil { return err	} sd := bytes.Split(ev.Data, []byte("\n")) for i := range sd { if _, err := fmt.Fprintf(w, "data: %s\n", sd[i]); err != nil { return err	}	} if len(ev.Event) > 0 { if _, err := fmt.Fprintf(w, "event: %s\n", ev.Event); err != nil { return err	}	} if len(ev.Retry) > 0 { if _, err := fmt.Fprintf(w, "retry: %s\n", ev.Retry); err != nil { return err	}	}	} if len(ev.Comment) > 0 { if _, err := fmt.Fprintf(w, ": %s\n", ev.Comment); err != nil { return err	}	} if _, err := fmt.Fprint(w, "\n"); err != nil { return err	} return nil }

in the same folder as app create index.html

<!DOCTYPE html> <html> <body> <h1>Getting server updates</h1> <div id="result"></div> <script> // Example taken from: https://www.w3schools.com/html/html5_serversentevents.asp if (typeof (EventSource) !== "undefined") { const source = new EventSource("/sse"); source.onmessage = function (event) { document.getElementById("result").innerHTML += event.data + "<br>"; }; } else { document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events..."; } </script> </body> </html>
  1. Open http://localhost:8080 in your browser. You should see Ping messages streamed, assuming proxy middleware handles SSE requests as raw proxy
@aldas aldas changed the title proxy middleware should use raw http proxy for SSE requests proxy middleware should use raw proxy for SSE requests Apr 15, 2024
@aldas aldas changed the title proxy middleware should use raw proxy for SSE requests proxy middleware should use httputil.ReverseProxy for SSE requests Apr 15, 2024
@aldas aldas merged commit e0f2a02 into labstack:master Apr 15, 2024
@aldas aldas deleted the proxy_sse branch April 15, 2024 18:12
nono referenced this pull request in cozy/cozy-stack Apr 22, 2024
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/labstack/echo/v4](https://togithub.com/labstack/echo) | `v4.11.4` -> `v4.12.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2flabstack%2fecho%2fv4/v4.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2flabstack%2fecho%2fv4/v4.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2flabstack%2fecho%2fv4/v4.11.4/v4.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2flabstack%2fecho%2fv4/v4.11.4/v4.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>labstack/echo (github.com/labstack/echo/v4)</summary> ### [`v4.12.0`](https://togithub.com/labstack/echo/blob/HEAD/CHANGELOG.md#v4120---2024-04-15) [Compare Source](https://togithub.com/labstack/echo/compare/v4.11.4...v4.12.0) **Security** - Update golang.org/x/net dep because of [GO-2024-2687](https://pkg.go.dev/vuln/GO-2024-2687) by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2625](https://togithub.com/labstack/echo/pull/2625) **Enhancements** - binder: make binding to Map work better with string destinations by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2554](https://togithub.com/labstack/echo/pull/2554) - README.md: add Encore as sponsor by [@&#8203;marcuskohlberg](https://togithub.com/marcuskohlberg) in [https://github.com/labstack/echo/pull/2579](https://togithub.com/labstack/echo/pull/2579) - Reorder paragraphs in README.md by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2581](https://togithub.com/labstack/echo/pull/2581) - CI: upgrade actions/checkout to v4 by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2584](https://togithub.com/labstack/echo/pull/2584) - Remove default charset from 'application/json' Content-Type header by [@&#8203;doortts](https://togithub.com/doortts) in [https://github.com/labstack/echo/pull/2568](https://togithub.com/labstack/echo/pull/2568) - CI: Use Go 1.22 by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2588](https://togithub.com/labstack/echo/pull/2588) - binder: allow binding to a nil map by [@&#8203;georgmu](https://togithub.com/georgmu) in [https://github.com/labstack/echo/pull/2574](https://togithub.com/labstack/echo/pull/2574) - Add Skipper Unit Test In BasicBasicAuthConfig and Add More Detail Explanation regarding BasicAuthValidator by [@&#8203;RyoKusnadi](https://togithub.com/RyoKusnadi) in [https://github.com/labstack/echo/pull/2461](https://togithub.com/labstack/echo/pull/2461) - fix some typos by [@&#8203;teslaedison](https://togithub.com/teslaedison) in [https://github.com/labstack/echo/pull/2603](https://togithub.com/labstack/echo/pull/2603) - fix: some typos by [@&#8203;pomadev](https://togithub.com/pomadev) in [https://github.com/labstack/echo/pull/2596](https://togithub.com/labstack/echo/pull/2596) - Allow ResponseWriters to unwrap writers when flushing/hijacking by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2595](https://togithub.com/labstack/echo/pull/2595) - Add SPDX licence comments to files. by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2604](https://togithub.com/labstack/echo/pull/2604) - Upgrade deps by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2605](https://togithub.com/labstack/echo/pull/2605) - Change type definition blocks to single declarations. This helps copy… by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2606](https://togithub.com/labstack/echo/pull/2606) - Fix Real IP logic by [@&#8203;cl-bvl](https://togithub.com/cl-bvl) in [https://github.com/labstack/echo/pull/2550](https://togithub.com/labstack/echo/pull/2550) - Default binder can use `UnmarshalParams(params []string) error` inter… by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2607](https://togithub.com/labstack/echo/pull/2607) - Default binder can bind pointer to slice as struct field. For example `*[]string` by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2608](https://togithub.com/labstack/echo/pull/2608) - Remove maxparam dependence from Context by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2611](https://togithub.com/labstack/echo/pull/2611) - When route is registered with empty path it is normalized to `/`. by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2616](https://togithub.com/labstack/echo/pull/2616) - proxy middleware should use httputil.ReverseProxy for SSE requests by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2624](https://togithub.com/labstack/echo/pull/2624) </details> --- ### Configuration 📅 **Schedule**: Branch creation - "before 6am on Monday" in timezone Europe/Paris, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/cozy/cozy-stack). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zMTMuMSIsInVwZGF0ZWRJblZlciI6IjM3LjMxMy4xIiwidGFyZ2V0QnJhbmNoIjoibWFzdGVyIiwibGFiZWxzIjpbXX0=-->
github-merge-queue bot referenced this pull request in infratographer/x Aug 8, 2024
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [github.com/labstack/echo/v4](https://togithub.com/labstack/echo) | `v4.11.4` -> `v4.12.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2flabstack%2fecho%2fv4/v4.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/go/github.com%2flabstack%2fecho%2fv4/v4.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/go/github.com%2flabstack%2fecho%2fv4/v4.11.4/v4.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2flabstack%2fecho%2fv4/v4.11.4/v4.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>labstack/echo (github.com/labstack/echo/v4)</summary> ### [`v4.12.0`](https://togithub.com/labstack/echo/blob/HEAD/CHANGELOG.md#v4120---2024-04-15) [Compare Source](https://togithub.com/labstack/echo/compare/v4.11.4...v4.12.0) **Security** - Update golang.org/x/net dep because of [GO-2024-2687](https://pkg.go.dev/vuln/GO-2024-2687) by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2625](https://togithub.com/labstack/echo/pull/2625) **Enhancements** - binder: make binding to Map work better with string destinations by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2554](https://togithub.com/labstack/echo/pull/2554) - README.md: add Encore as sponsor by [@&#8203;marcuskohlberg](https://togithub.com/marcuskohlberg) in [https://github.com/labstack/echo/pull/2579](https://togithub.com/labstack/echo/pull/2579) - Reorder paragraphs in README.md by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2581](https://togithub.com/labstack/echo/pull/2581) - CI: upgrade actions/checkout to v4 by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2584](https://togithub.com/labstack/echo/pull/2584) - Remove default charset from 'application/json' Content-Type header by [@&#8203;doortts](https://togithub.com/doortts) in [https://github.com/labstack/echo/pull/2568](https://togithub.com/labstack/echo/pull/2568) - CI: Use Go 1.22 by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2588](https://togithub.com/labstack/echo/pull/2588) - binder: allow binding to a nil map by [@&#8203;georgmu](https://togithub.com/georgmu) in [https://github.com/labstack/echo/pull/2574](https://togithub.com/labstack/echo/pull/2574) - Add Skipper Unit Test In BasicBasicAuthConfig and Add More Detail Explanation regarding BasicAuthValidator by [@&#8203;RyoKusnadi](https://togithub.com/RyoKusnadi) in [https://github.com/labstack/echo/pull/2461](https://togithub.com/labstack/echo/pull/2461) - fix some typos by [@&#8203;teslaedison](https://togithub.com/teslaedison) in [https://github.com/labstack/echo/pull/2603](https://togithub.com/labstack/echo/pull/2603) - fix: some typos by [@&#8203;pomadev](https://togithub.com/pomadev) in [https://github.com/labstack/echo/pull/2596](https://togithub.com/labstack/echo/pull/2596) - Allow ResponseWriters to unwrap writers when flushing/hijacking by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2595](https://togithub.com/labstack/echo/pull/2595) - Add SPDX licence comments to files. by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2604](https://togithub.com/labstack/echo/pull/2604) - Upgrade deps by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2605](https://togithub.com/labstack/echo/pull/2605) - Change type definition blocks to single declarations. This helps copy… by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2606](https://togithub.com/labstack/echo/pull/2606) - Fix Real IP logic by [@&#8203;cl-bvl](https://togithub.com/cl-bvl) in [https://github.com/labstack/echo/pull/2550](https://togithub.com/labstack/echo/pull/2550) - Default binder can use `UnmarshalParams(params []string) error` inter… by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2607](https://togithub.com/labstack/echo/pull/2607) - Default binder can bind pointer to slice as struct field. For example `*[]string` by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2608](https://togithub.com/labstack/echo/pull/2608) - Remove maxparam dependence from Context by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2611](https://togithub.com/labstack/echo/pull/2611) - When route is registered with empty path it is normalized to `/`. by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2616](https://togithub.com/labstack/echo/pull/2616) - proxy middleware should use httputil.ReverseProxy for SSE requests by [@&#8203;aldas](https://togithub.com/aldas) in [https://github.com/labstack/echo/pull/2624](https://togithub.com/labstack/echo/pull/2624) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/infratographer/x). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yOTMuMCIsInVwZGF0ZWRJblZlciI6IjM3LjQzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> --------- Signed-off-by: Mike Mason <mimason@equinix.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Mike Mason <mimason@equinix.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant