-
Notifications
You must be signed in to change notification settings - Fork 8
fix(httpx,gormx): unencrypted-HTTP2 via Protocols, resource caps, and three ltefield tags that reject valid configs #625
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
Merged
Merged
Changes from 1 commit
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
dd01b51
fix(httpx): replace deprecated h2c.NewHandler, add body size and conn…
molon d112dfd
docs(httpx): spell out that MaxConnections counts connections, not re…
molon d09e6dc
feat(httpx): make maxConcurrentStreams configurable
molon 8123505
docs(httpx): English comments; pin the compat guarantees that matter …
molon 8650e86
test(httpx): cover MaxConnections, reject negative limits — per review
molon fcc6177
fix(gormx): default maxOpenConns to 0 (unlimited), and move the idle/…
molon 4a1381c
fix(gormx,httpx): move the three "0 means unlimited" pairings out of …
molon e184533
docs(httpx): MaxConnections 默认 0 才是常态,说清它两头都保护不到
molon 0b466e3
docs(gormx,httpx): state the mechanics, not a recommendation
molon a79aa94
fix(gormx,httpx): use confx's stop_if instead of hand-checking in the…
molon 4b7b738
chore: bump confx to the released stop_if / stop_unless
molon 679377d
docs(httpx): translate the test comments added by this PR to English
molon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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 |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| package httpx_test | ||
|
|
||
| import ( | ||
| "context" | ||
| "crypto/tls" | ||
| "io" | ||
| "net" | ||
| "net/http" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| "golang.org/x/net/http2" | ||
|
|
||
| "github.com/qor5/x/v3/httpx" | ||
| ) | ||
|
|
||
| // serve 起一个监听在随机端口上的 server,返回其地址。 | ||
| func serve(t *testing.T, conf *httpx.ServerConfig, handler http.Handler) string { | ||
| t.Helper() | ||
|
|
||
| srv, err := httpx.NewServer(conf, handler) | ||
| require.NoError(t, err) | ||
|
|
||
| ln, err := net.Listen("tcp", "127.0.0.1:0") | ||
| require.NoError(t, err) | ||
|
|
||
| go func() { _ = srv.Serve(ln) }() | ||
| t.Cleanup(func() { _ = srv.Close() }) | ||
|
|
||
| return ln.Addr().String() | ||
| } | ||
|
|
||
| // h2cClient 用 prior-knowledge 模式(直接发 HTTP/2 前导)连明文端口, | ||
| // 这正是 Envoy / gRPC 客户端在 appProtocol=h2c 下的行为。 | ||
| func h2cClient() *http.Client { | ||
| return &http.Client{ | ||
| Transport: &http2.Transport{ | ||
| AllowHTTP: true, | ||
| DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) { | ||
| return (&net.Dialer{}).DialContext(ctx, network, addr) | ||
| }, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| // 迁移到 http.Server.Protocols 之后,明文 HTTP/2 必须仍然可用—— | ||
| // 这是替换掉已废弃的 h2c.NewHandler 时最需要守住的行为。 | ||
| func TestNewServer_H2C(t *testing.T) { | ||
| addr := serve(t, &httpx.ServerConfig{Address: ":0"}, | ||
| http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| _, _ = io.WriteString(w, r.Proto) | ||
| })) | ||
|
|
||
| resp, err := h2cClient().Get("http://" + addr) | ||
| require.NoError(t, err) | ||
| defer func() { _ = resp.Body.Close() }() | ||
|
|
||
| body, err := io.ReadAll(resp.Body) | ||
| require.NoError(t, err) | ||
| require.Equal(t, "HTTP/2.0", string(body)) | ||
| } | ||
|
|
||
| // 同一个 server 必须同时还能服务 HTTP/1.1。 | ||
| func TestNewServer_HTTP1StillWorks(t *testing.T) { | ||
| addr := serve(t, &httpx.ServerConfig{Address: ":0"}, | ||
| http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| _, _ = io.WriteString(w, r.Proto) | ||
| })) | ||
|
|
||
| resp, err := http.Get("http://" + addr) | ||
| require.NoError(t, err) | ||
| defer func() { _ = resp.Body.Close() }() | ||
|
|
||
| body, err := io.ReadAll(resp.Body) | ||
| require.NoError(t, err) | ||
| require.Equal(t, "HTTP/1.1", string(body)) | ||
| } | ||
|
|
||
| func TestNewServer_MaxRequestBodySize(t *testing.T) { | ||
| const limit = 16 | ||
|
|
||
| handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| if _, err := io.ReadAll(r.Body); err != nil { | ||
| w.WriteHeader(http.StatusRequestEntityTooLarge) | ||
| return | ||
| } | ||
| w.WriteHeader(http.StatusOK) | ||
| }) | ||
|
|
||
| t.Run("under the limit passes", func(t *testing.T) { | ||
| addr := serve(t, &httpx.ServerConfig{Address: ":0", MaxRequestBodySize: limit}, handler) | ||
|
|
||
| resp, err := http.Post("http://"+addr, "text/plain", strings.NewReader("short")) | ||
| require.NoError(t, err) | ||
| defer func() { _ = resp.Body.Close() }() | ||
| require.Equal(t, http.StatusOK, resp.StatusCode) | ||
| }) | ||
|
|
||
| t.Run("over the limit is rejected", func(t *testing.T) { | ||
| addr := serve(t, &httpx.ServerConfig{Address: ":0", MaxRequestBodySize: limit}, handler) | ||
|
|
||
| resp, err := http.Post("http://"+addr, "text/plain", strings.NewReader(strings.Repeat("x", limit*4))) | ||
| require.NoError(t, err) | ||
| defer func() { _ = resp.Body.Close() }() | ||
| require.Equal(t, http.StatusRequestEntityTooLarge, resp.StatusCode) | ||
| }) | ||
|
|
||
| t.Run("zero means unlimited", func(t *testing.T) { | ||
| addr := serve(t, &httpx.ServerConfig{Address: ":0"}, handler) | ||
|
|
||
| resp, err := http.Post("http://"+addr, "text/plain", strings.NewReader(strings.Repeat("x", limit*4))) | ||
| require.NoError(t, err) | ||
| defer func() { _ = resp.Body.Close() }() | ||
| require.Equal(t, http.StatusOK, resp.StatusCode) | ||
| }) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.