Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ require (
go.opentelemetry.io/otel/trace v1.38.0
go.uber.org/automaxprocs v1.6.0
go.uber.org/zap v1.27.1
golang.org/x/net v0.47.0
golang.org/x/sync v0.18.0
golang.org/x/tools v0.39.0
gomodules.xyz/jsonpatch/v2 v2.5.0
Expand Down Expand Up @@ -89,6 +88,7 @@ require (
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac // indirect
golang.org/x/mod v0.30.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/term v0.37.0 // indirect
Expand Down
69 changes: 0 additions & 69 deletions network/h2c.go

This file was deleted.

38 changes: 38 additions & 0 deletions network/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
Copyright 2025 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package network

import (
"net/http"
"time"
)

func NewServer(addr string, h http.Handler) *http.Server {
var protocols http.Protocols
protocols.SetHTTP1(true)
protocols.SetHTTP2(true)
protocols.SetUnencryptedHTTP2(true)

return &http.Server{
Addr: addr,
Handler: h,
Protocols: &protocols,

// https://medium.com/a-journey-with-go/go-understand-and-mitigate-slowloris-attack-711c1b1403f6
ReadHeaderTimeout: time.Minute,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about MaxHeaderBytes to make it configurable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure - circling back on this PR I realize we can't just remove the h2c upgrade flow because that can break existing workloads.

In theory we need

  1. Add support for h2 prior knowledge
  2. deprecated h2c upgrade flow
  3. then eventually drop h2c upgrade flow in some future release

}
}
87 changes: 73 additions & 14 deletions network/transports.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,61 +117,120 @@ func dialBackOffHelper(ctx context.Context, network, address string, bo wait.Bac
return nil, fmt.Errorf("%w %s after %.2fs", ErrTimeoutDialing, address, elapsed.Seconds())
}

func newHTTPTransport(disableKeepAlives, disableCompression bool, maxIdle, maxIdlePerHost int) http.RoundTripper {
func newHTTPTransport(
disableKeepAlives,
disableCompression bool,
maxIdle,
maxIdlePerHost int,
) *http.Transport {
var protocols http.Protocols
protocols.SetHTTP1(true)

transport := http.DefaultTransport.(*http.Transport).Clone()
transport.DialContext = DialWithBackOff
transport.DisableKeepAlives = disableKeepAlives
transport.MaxIdleConns = maxIdle
transport.MaxIdleConnsPerHost = maxIdlePerHost
transport.ForceAttemptHTTP2 = false
transport.DisableCompression = disableCompression
transport.Protocols = &protocols

return transport
}

type DialTLSContextFunc func(ctx context.Context, network, addr string) (net.Conn, error)

func newHTTPSTransport(disableKeepAlives, disableCompression bool, maxIdle, maxIdlePerHost int, tlsContext DialTLSContextFunc) http.RoundTripper {
func newHTTPSTransport(
disableKeepAlives,
disableCompression bool,
maxIdle,
maxIdlePerHost int,
tlsContext DialTLSContextFunc,
) *http.Transport {
var protocols http.Protocols
protocols.SetHTTP1(true)

transport := http.DefaultTransport.(*http.Transport).Clone()
transport.DisableKeepAlives = disableKeepAlives
transport.MaxIdleConns = maxIdle
transport.MaxIdleConnsPerHost = maxIdlePerHost
transport.ForceAttemptHTTP2 = false
transport.DisableCompression = disableCompression
transport.DialTLSContext = tlsContext
transport.Protocols = &protocols

return transport
}

// NewProberTransport creates a RoundTripper that is useful for probing,
// since it will not cache connections.
func NewProberTransport() http.RoundTripper {
return newAutoTransport(
newHTTPTransport(true /*disable keep-alives*/, false /*disable auto-compression*/, 0, 0 /*no caching*/),
NewH2CTransport())
http := newHTTPTransport(
true, /*disable keep-alives*/
false, /*disable auto-compression*/
0, /*max idle*/
0, /*no caching*/
)

// h2 prior knowledge
h2 := http.Clone()
h2.Protocols.SetHTTP1(false)
h2.Protocols.SetUnencryptedHTTP2(true)

return newAutoTransport(http, h2)
}

// NewProxyAutoTLSTransport is same with NewProxyAutoTransport but it has DialTLSContextFunc to create HTTPS request.
func NewProxyAutoTLSTransport(maxIdle, maxIdlePerHost int, tlsContext DialTLSContextFunc) http.RoundTripper {
return newAutoTransport(
newHTTPSTransport(false /*disable keep-alives*/, true /*disable auto-compression*/, maxIdle, maxIdlePerHost, tlsContext),
newH2Transport(true /*disable auto-compression*/, tlsContext))
https := newHTTPSTransport(
false, /*disable keep-alives*/
true, /*disable auto-compression*/
maxIdle,
maxIdlePerHost,
tlsContext,
)

h2 := https.Clone()
h2.Protocols.SetHTTP1(false)
h2.Protocols.SetHTTP2(true)
h2.Protocols.SetUnencryptedHTTP2(true)

return newAutoTransport(https, h2)
}

// NewAutoTransport creates a RoundTripper that can use appropriate transport
// based on the request's HTTP version.
func NewAutoTransport(maxIdle, maxIdlePerHost int) http.RoundTripper {
return newAutoTransport(
newHTTPTransport(false /*disable keep-alives*/, false /*disable auto-compression*/, maxIdle, maxIdlePerHost),
newH2CTransport(false /*disable auto-compression*/))
http := newHTTPTransport(
false, /*disable keep-alives*/
false, /*disable auto-compression*/
maxIdle,
maxIdlePerHost,
)

h2 := http.Clone()
h2.Protocols.SetHTTP1(false)
h2.Protocols.SetUnencryptedHTTP2(true)

return newAutoTransport(http, h2)
}

// NewProxyAutoTransport creates a RoundTripper suitable for use by a reverse
// proxy. The returned transport uses HTTP or H2C based on the request's HTTP
// version. The transport has DisableCompression set to true.
func NewProxyAutoTransport(maxIdle, maxIdlePerHost int) http.RoundTripper {
return newAutoTransport(
newHTTPTransport(false /*disable keep-alives*/, true /*disable auto-compression*/, maxIdle, maxIdlePerHost),
newH2CTransport(true /*disable auto-compression*/))
http := newHTTPTransport(
false, /*disable keep-alives*/
true, /*disable auto-compression*/
maxIdle,
maxIdlePerHost,
)

h2 := http.Clone()
h2.Protocols.SetHTTP1(false)
h2.Protocols.SetUnencryptedHTTP2(true)

return newAutoTransport(http, h2)
}

// AutoTransport uses h2c for HTTP2 requests and falls back to `http.DefaultTransport` for all others
Expand Down
Loading
Loading