-
Notifications
You must be signed in to change notification settings - Fork 266
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
51eb134
commit 71c7226
Showing
2 changed files
with
50 additions
and
33 deletions.
There are no files selected for viewing
63 changes: 38 additions & 25 deletions
63
content/en/docs/hertz/tutorials/framework-exten/response_writer.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,73 @@ | ||
--- | ||
title: "Response Writer Extension" | ||
linkTitle: "Response Writer Extension" | ||
date: 2023-03-10 | ||
date: 2023-09-22 | ||
weight: 6 | ||
keywords: ["Response Writer Extension", "Response.HijackWriter"] | ||
keywords: [ "Response Writer Extension", "Response.HijackWriter" ] | ||
description: "Response Writer Extension provided by Hertz." | ||
|
||
--- | ||
|
||
Hertz provides response writer extension, if users need to hijack the writer of the response, they can implement the corresponding interfaces according to their needs. | ||
According to Hertz's [layered architecture](https://www.cloudwego.io/zh/docs/hertz/overview/), the actual write | ||
operation of the HTTP response is performed after the application layer user processing logic returns. Under this | ||
constraint, users cannot flexibly control the behavior of write operations on demand. This limitation is especially | ||
obvious in scenarios such as controlling chunked encoding write logic | ||
and [SSE](https://github.com/hertz-contrib/sse#hertz-sse). | ||
|
||
## Interface Definition | ||
To solve this problem, Hertz provides an extension called "Response Writer Hijacking" that can vertically penetrate the | ||
limitations brought by the layered architecture in an orthogonal way. It allows users to freely customize the logic of | ||
writing responses in the application layer according to their own needs, improving the framework's ease of use. | ||
|
||
## Core Design | ||
|
||
### Interface Definition | ||
|
||
interface is defined in `pkg/network/writer`. | ||
|
||
```go | ||
type ExtWriter interface { | ||
io.Writer | ||
Flush() error | ||
io.Writer | ||
Flush() error | ||
|
||
// Finalize will be called by framework before the writer is released. | ||
// Implementations must guarantee that Finalize is safe for multiple calls. | ||
Finalize() error | ||
// Finalize will be called by framework before the writer is released. | ||
// Implementations must guarantee that Finalize is safe for multiple calls. | ||
Finalize() error | ||
} | ||
``` | ||
|
||
### Hijack Your Own Response Writer | ||
|
||
Hertz provides `Response.HijackWriter` in `app.RequestContext` to allow users to hijack their own response writer, which provides another way for response writing process. | ||
Hertz provides `Response.HijackWriter` in `app.RequestContext` to allow users to hijack their own response writer, which | ||
provides another way for response writing process. | ||
|
||
Example: | ||
|
||
```go | ||
h.GET("/hijack", func(c context.Context, ctx *app.RequestContext) { | ||
// Hijack the writer of response | ||
ctx.Response.HijackWriter(yourResponseWriter) | ||
}) | ||
h.GET("/hijack", func (c context.Context, ctx *app.RequestContext) { | ||
// Hijack the writer of response | ||
ctx.Response.HijackWriter(**yourResponseWriter**) | ||
}) | ||
``` | ||
|
||
## Supported Response Writer Extension | ||
|
||
Hertz provides `NewChunkedBodyWriter` to create a response writer which allow users to flush chunk immediately during the handler process, it is defined under `pkg/protocol/http1/resp/writer`, and you can implement your own response writer. | ||
- `ChunkedBodyWriter`: Hertz provides `NewChunkedBodyWriter` to create a response writer which allow users to flush chunk immediately during | ||
the handler process, it is defined under `pkg/protocol/http1/resp/writer`, and you can implement your own response | ||
writer. | ||
|
||
### ChunkedBodyWriter | ||
|
||
Example: | ||
|
||
```go | ||
h.GET("/flush/chunk", func(c context.Context, ctx *app.RequestContext) { | ||
// Hijack the writer of response | ||
ctx.Response.HijackWriter(resp.NewChunkedBodyWriter(&ctx.Response, ctx.GetWriter())) | ||
|
||
for i := 0; i < 10; i++ { | ||
ctx.Write([]byte(fmt.Sprintf("chunk %d: %s", i, strings.Repeat("hi~", i)))) // nolint: errcheck | ||
ctx.Flush() // nolint: errcheck | ||
time.Sleep(200 * time.Millisecond) | ||
} | ||
}) | ||
h.GET("/flush/chunk", func (c context.Context, ctx *app.RequestContext) { | ||
// Hijack the writer of response | ||
ctx.Response.HijackWriter(resp.NewChunkedBodyWriter(&ctx.Response, ctx.GetWriter())) | ||
|
||
for i := 0; i < 10; i++ { | ||
ctx.Write([]byte(fmt.Sprintf("chunk %d: %s", i, strings.Repeat("hi~", i)))) // nolint: errcheck | ||
ctx.Flush() // nolint: errcheck | ||
time.Sleep(200 * time.Millisecond) | ||
} | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71c7226
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.
Successfully deployed to the following URLs:
cloudwego – ./
cloudwego-cloudwego.vercel.app
cloudwego.vercel.app
cloudwego-git-main-cloudwego.vercel.app
www.cloudwego.io
vercel.cloudwego.io
cloudwego.io