-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
🔥 Feature (v3): Add buffered streaming support #3131
Changes from all commits
885f807
1ff06dc
c977b38
024ac5e
2282a35
7b238d1
95b1745
02b7ce2
d82e3bc
4d36527
1724121
0b07295
c59764e
76dee57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -5,6 +5,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||
package fiber | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
"bufio" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
"bytes" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
"context" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
"crypto/tls" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1671,6 +1672,13 @@ func (c *DefaultCtx) SendStream(stream io.Reader, size ...int) error { | |||||||||||||||||||||||||||||||||||||||||||||||||||
return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
// SendStreamWriter sets response body stream writer | ||||||||||||||||||||||||||||||||||||||||||||||||||||
func (c *DefaultCtx) SendStreamWriter(streamWriter func(*bufio.Writer)) error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1675
to
+1676
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add comprehensive documentation for the new public API method. As this is a new public API method for buffered streaming support, it should include:
Apply this diff to improve the documentation: -// SendStreamWriter sets response body stream writer
+// SendStreamWriter sets the response body stream writer for sending chunked data through a callback function.
+//
+// The callback function is called when the response is being written to the client.
+// This allows for efficient memory usage as data can be written in chunks.
+//
+// Perfect for:
+// - Server-Sent Events (SSE)
+// - Large file downloads
+// - Real-time data streaming
+//
+// Example:
+// app.Get("/sse", func(c fiber.Ctx) error {
+// c.Set("Content-Type", "text/event-stream")
+// c.Set("Cache-Control", "no-cache")
+// c.Set("Connection", "keep-alive")
+// c.Set("Transfer-Encoding", "chunked")
+//
+// return c.SendStreamWriter(func(w *bufio.Writer) {
+// fmt.Fprintf(w, "event: message\ndata: Hello SSE\n\n")
+// w.Flush()
+// })
+// }) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
c.fasthttp.Response.SetBodyStreamWriter(fasthttp.StreamWriter(streamWriter)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
// Set sets the response's HTTP header field to the specified key, value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
func (c *DefaultCtx) Set(key, val string) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
c.fasthttp.Response.Header.Set(key, val) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -268,6 +268,7 @@ DRAFT section | |
- Reset | ||
- Schema -> ExpressJs like | ||
- SendStream -> ExpressJs like | ||
- SendStreamWriter | ||
- SendString -> ExpressJs like | ||
- String -> ExpressJs like | ||
- ViewBind -> instead of Bind | ||
|
@@ -296,6 +297,43 @@ DRAFT section | |
- UserContext has been renamed to Context which returns a context.Context object. | ||
- SetUserContext has been renamed to SetContext. | ||
|
||
### SendStreamWriter | ||
|
||
In v3, we added support for buffered streaming by providing the new method `SendStreamWriter()`. | ||
|
||
```go | ||
func (c Ctx) SendStreamWriter(streamWriter func(w *bufio.Writer)) | ||
``` | ||
|
||
With this new method, you can implement: | ||
|
||
- Server-Side Events (SSE) | ||
- Large file downloads | ||
- Live data streaming | ||
|
||
```go | ||
app.Get("/sse", func(c fiber.Ctx) { | ||
c.Set("Content-Type", "text/event-stream") | ||
c.Set("Cache-Control", "no-cache") | ||
c.Set("Connection", "keep-alive") | ||
c.Set("Transfer-Encoding", "chunked") | ||
|
||
return c.SendStreamWriter(func(w *bufio.Writer) { | ||
for { | ||
fmt.Fprintf(w, "event: my-event\n") | ||
fmt.Fprintf(w, "data: Hello SSE\n\n") | ||
|
||
if err := w.Flush(); err != nil { | ||
log.Print("Client disconnected!") | ||
return | ||
} | ||
} | ||
}) | ||
}) | ||
``` | ||
Comment on lines
+315
to
+333
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance the SSE example with best practices and error handling. The Server-Sent Events example could be improved by:
app.Get("/sse", func(c fiber.Ctx) {
c.Set("Content-Type", "text/event-stream")
c.Set("Cache-Control", "no-cache")
c.Set("Connection", "keep-alive")
c.Set("Transfer-Encoding", "chunked")
+ // Create a channel to handle cancellation
+ done := make(chan bool)
+
+ // Handle client disconnection
+ c.Context().SetBodyStreamWriter(func(w *bufio.Writer) {
+ ticker := time.NewTicker(time.Second)
+ defer ticker.Stop()
+
+ for {
+ select {
+ case <-done:
+ return
+ case <-ticker.C:
+ // Write event with proper error handling
+ if _, err := fmt.Fprintf(w, "event: my-event\n"); err != nil {
+ log.Printf("Error writing event: %v", err)
+ return
+ }
+ if _, err := fmt.Fprintf(w, "data: Hello SSE\n\n"); err != nil {
+ log.Printf("Error writing data: %v", err)
+ return
+ }
+
+ if err := w.Flush(); err != nil {
+ log.Printf("Client disconnected: %v", err)
+ return
+ }
+ }
+ }
+ })
+
+ // Clean up when the handler returns
+ defer close(done)
+
return c.SendStreamWriter(func(w *bufio.Writer) {
for {
fmt.Fprintf(w, "event: my-event\n")
fmt.Fprintf(w, "data: Hello SSE\n\n")
if err := w.Flush(); err != nil {
log.Print("Client disconnected!")
return
}
}
})
})
|
||
|
||
You can find more details about this feature in [/docs/api/ctx.md](./api/ctx.md). | ||
|
||
--- | ||
|
||
## 🌎 Client package | ||
|
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.
🛠️ Refactor suggestion
Add comprehensive documentation for the new public API method.
The method lacks proper documentation. As this is a new public API method for buffered streaming support, it should include:
Add documentation like this:
📝 Committable suggestion
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.
I think we should add an example/recipe about this feature after the PR get merged
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.
@efectn, that's a great idea. Adding an example or recipe about this feature after the PR is merged will be beneficial for users. Would you like me to open a new GitHub issue to track this follow-up action?
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.
Yes
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.