Skip to content
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

HTTP2 support in router #2953

Merged
merged 42 commits into from
Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
e1357bc
initial commit
Amila-Rukshan May 24, 2022
869abce
Merge branch 'wso2:main' into http2-support
Amila-Rukshan May 24, 2022
4c89336
enable upsteam http2
Amila-Rukshan May 25, 2022
86e8f5f
Merge branch 'wso2:main' into http2-support
Amila-Rukshan May 26, 2022
76f70f4
checked http2 configs
Amila-Rukshan May 27, 2022
5bbb5a1
Merge branch 'http2-support' of https://github.com/Amila-Rukshan/prod…
Amila-Rukshan May 27, 2022
1399843
commented new code
Amila-Rukshan May 27, 2022
2a9ec20
http2 server clear text and tls with tests
Amila-Rukshan Jun 2, 2022
bb6ec7e
Merge branch 'wso2:main' into http2-support
Amila-Rukshan Jun 2, 2022
5a1fbf8
Merge branch 'http2-support' of https://github.com/Amila-Rukshan/prod…
Amila-Rukshan Jun 2, 2022
0cf9ad9
new lines added at the end of files duplicate test class names corrected
Amila-Rukshan Jun 3, 2022
0110d42
http2 codec config in router added and formatting
Amila-Rukshan Jun 4, 2022
ab154e8
http2 client and tests added
Amila-Rukshan Jun 4, 2022
de1ce94
failing test case fixed
Amila-Rukshan Jun 6, 2022
ae1384a
default http2 options added for assuming untrusted upstreams
Amila-Rukshan Jun 6, 2022
42390c2
address review comments
Amila-Rukshan Jun 7, 2022
b802f7d
alpn protocols limited use when only http2 enabled
Amila-Rukshan Jun 7, 2022
cae2be6
Merge branch 'wso2:main' into http2-support
Amila-Rukshan Jun 7, 2022
f9eda01
extension name changed
Amila-Rukshan Jun 8, 2022
9e793f4
Merge branch 'http2-support' of https://github.com/Amila-Rukshan/prod…
Amila-Rukshan Jun 8, 2022
9dbf293
apim secured api test case added
Amila-Rukshan Jun 8, 2022
53af4f1
test cases updated
Amila-Rukshan Jun 8, 2022
128e498
Merge branch 'wso2:main' into http2-support
Amila-Rukshan Jun 8, 2022
94f9c5e
only http1 or http2 options added to fix runtime failures
Amila-Rukshan Jun 9, 2022
23ce80e
use HttpProtocolOptions_ExplicitHttpConfig added to avoid deprecated …
Amila-Rukshan Jun 9, 2022
9a21ea3
Merge branch 'wso2:main' into http2-support
Amila-Rukshan Jun 9, 2022
901c00f
http2 options defaults added
Amila-Rukshan Jun 9, 2022
bcfe975
license year fixed
Amila-Rukshan Jun 9, 2022
e5ffee1
Merge branch 'wso2:main' into http2-support
Amila-Rukshan Jun 20, 2022
ea24a78
Merge branch 'wso2:main' into http2-support
Amila-Rukshan Jun 29, 2022
a004d16
fomatting issue fixed
Amila-Rukshan Jun 29, 2022
37b2fed
fomatting issue
Amila-Rukshan Jun 29, 2022
d75e08d
new line added
Amila-Rukshan Jun 29, 2022
92e2078
Merge branch 'wso2:main' into http2-support
Amila-Rukshan Jun 29, 2022
7551619
k8s config-toml upadated with http2 options
Amila-Rukshan Jun 29, 2022
8505d01
Merge branch 'http2-support' of https://github.com/Amila-Rukshan/prod…
Amila-Rukshan Jun 29, 2022
225c23f
Merge branch 'wso2:main' into http2-support
Amila-Rukshan Jun 29, 2022
8ac01d3
removed default http2 upstream configs from config.toml
Amila-Rukshan Jul 5, 2022
23b8a51
remove unwanted types for hashmap
Amila-Rukshan Jul 5, 2022
3d05bef
removed http2 default configs from k8s config map
Amila-Rukshan Jul 5, 2022
5aed0d7
Merge branch 'main' into http2-support
Amila-Rukshan Jul 6, 2022
57d07c5
Merge branch 'main' into http2-support
Amila-Rukshan Jul 11, 2022
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
5 changes: 5 additions & 0 deletions adapter/config/default_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ var defaultConfig = &Config{
ListenerPort: 9090,
SecuredListenerHost: "0.0.0.0",
SecuredListenerPort: 9095,
ListenerCodecType: "AUTO",
ClusterTimeoutInSeconds: 20,
EnforcerResponseTimeoutInSeconds: 20,
UseRemoteAddress: false,
Expand Down Expand Up @@ -119,6 +120,10 @@ var defaultConfig = &Config{
DNSRefreshRate: 5000,
RespectDNSTtl: false,
},
HTTP2: upstreamHTTP2Options{
HpackTableSize: 4096,
MaxConcurrentStreams: 2147483647,
},
},
Downstream: envoyDownstream{
TLS: downstreamTLS{
Expand Down
7 changes: 7 additions & 0 deletions adapter/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ type envoy struct {
ListenerPort uint32
SecuredListenerHost string
SecuredListenerPort uint32
ListenerCodecType string
ClusterTimeoutInSeconds time.Duration
EnforcerResponseTimeoutInSeconds time.Duration `default:"20"`
KeyStore keystore
Expand Down Expand Up @@ -225,6 +226,7 @@ type envoyUpstream struct {
Health upstreamHealth
DNS upstreamDNS
Retry upstreamRetry
HTTP2 upstreamHTTP2Options
}

// Envoy Downstream Related Configurations
Expand Down Expand Up @@ -265,6 +267,11 @@ type upstreamDNS struct {
RespectDNSTtl bool
}

type upstreamHTTP2Options struct {
HpackTableSize uint32
MaxConcurrentStreams uint32
}

type upstreamRetry struct {
MaxRetryCount uint32
BaseIntervalInMillis uint32
Expand Down
1 change: 1 addition & 0 deletions adapter/internal/oasparser/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const (
XWso2BasePath string = "x-wso2-basePath"
XWso2Label string = "x-wso2-label"
XWso2Cors string = "x-wso2-cors"
XWso2HTTP2BackendEnabled string = "x-wso2-http2-backend-enabled"
XThrottlingTier string = "x-throttling-tier"
XWso2ThrottlingTier string = "x-wso2-throttling-tier"
XAuthHeader string = "x-wso2-auth-header"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,9 @@ func TestCreateUpstreamTLSContext(t *testing.T) {
}}

tlsCert := generateTLSCert(defaultMgwKeyPath, defaultMgwCertPath)
upstreamTLSContextWithCerts := createUpstreamTLSContext(certByteArr, hostNameAddress)
upstreamTLSContextWithoutCerts := createUpstreamTLSContext(nil, hostNameAddress)
upstreamTLSContextWithIP := createUpstreamTLSContext(certByteArr, hostNameAddressWithIP)
upstreamTLSContextWithCerts := createUpstreamTLSContext(certByteArr, hostNameAddress, false)
upstreamTLSContextWithoutCerts := createUpstreamTLSContext(nil, hostNameAddress, false)
upstreamTLSContextWithIP := createUpstreamTLSContext(certByteArr, hostNameAddressWithIP, false)

assert.NotEmpty(t, upstreamTLSContextWithCerts, "Upstream TLS Context should not be null when certs provided")
assert.NotEmpty(t, upstreamTLSContextWithCerts.CommonTlsContext, "CommonTLSContext should not be "+
Expand Down
15 changes: 14 additions & 1 deletion adapter/internal/oasparser/envoyconf/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func createListeners(conf *config.Config) []*listenerv3.Listener {
var listeners []*listenerv3.Listener

manager := &hcmv3.HttpConnectionManager{
CodecType: hcmv3.HttpConnectionManager_AUTO,
CodecType: getListenerCodecType(conf.Envoy.ListenerCodecType),
StatPrefix: httpConManagerStartPrefix,
// WebSocket upgrades enabled from the HCM
UpgradeConfigs: []*hcmv3.HttpConnectionManager_UpgradeConfig{{
Expand Down Expand Up @@ -346,3 +346,16 @@ func getTracing(conf *config.Config) (*hcmv3.HttpConnectionManager_Tracing, erro

return tracing, nil
}

func getListenerCodecType(codecType string) hcmv3.HttpConnectionManager_CodecType {
switch codecType {
case "AUTO":
return hcmv3.HttpConnectionManager_AUTO
case "HTTP1":
return hcmv3.HttpConnectionManager_HTTP1
case "HTTP2":
return hcmv3.HttpConnectionManager_HTTP2
default:
return hcmv3.HttpConnectionManager_AUTO
}
}
53 changes: 49 additions & 4 deletions adapter/internal/oasparser/envoyconf/routes_with_clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
extAuthService "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
lua "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/lua/v3"
tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"

envoy_type_matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
"github.com/envoyproxy/go-control-plane/pkg/wellknown"

Expand All @@ -48,6 +49,7 @@ import (
"github.com/wso2/product-microgateway/adapter/internal/svcdiscovery"
"github.com/wso2/product-microgateway/adapter/pkg/logging"

upstreams_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes/any"
"github.com/golang/protobuf/ptypes/wrappers"
Expand Down Expand Up @@ -105,6 +107,7 @@ func CreateRoutesWithClusters(mgwSwagger model.MgwSwagger, upstreamCerts map[str
// check API level production endpoints available
if mgwSwagger.GetProdEndpoints() != nil && len(mgwSwagger.GetProdEndpoints().Endpoints) > 0 {
apiLevelEndpointProd := mgwSwagger.GetProdEndpoints()
apiLevelEndpointProd.HTTP2BackendEnabled = mgwSwagger.GetXWso2HTTP2BackendEnabled()
apiLevelBasePathProd = strings.TrimSuffix(apiLevelEndpointProd.Endpoints[0].Basepath, "/")
apiLevelClusterNameProd = getClusterName(apiLevelEndpointProd.EndpointPrefix, organizationID, vHost, apiTitle,
apiVersion, "")
Expand All @@ -130,6 +133,7 @@ func CreateRoutesWithClusters(mgwSwagger model.MgwSwagger, upstreamCerts map[str
if mgwSwagger.GetSandEndpoints() != nil && len(mgwSwagger.GetSandEndpoints().Endpoints) > 0 {
selectedBasePathSand := apiLevelBasePathProd
apiLevelEndpointSand := mgwSwagger.GetSandEndpoints()
apiLevelEndpointSand.HTTP2BackendEnabled = mgwSwagger.GetXWso2HTTP2BackendEnabled()
if apiLevelBasePathProd == "" && apiLevelClusterNameProd == "" {
// no production endpoint, assign sandbox endpoint basepath as apiLevelbasePath
apiLevelBasePathProd = strings.TrimSuffix(apiLevelEndpointSand.Endpoints[0].Basepath, "/")
Expand Down Expand Up @@ -535,7 +539,7 @@ func processEndpoints(clusterName string, clusterDetails *model.EndpointCluster,
epCert = defaultCerts
}

upstreamtlsContext := createUpstreamTLSContext(epCert, address)
upstreamtlsContext := createUpstreamTLSContext(epCert, address, clusterDetails.HTTP2BackendEnabled)
marshalledTLSContext, err := anypb.New(upstreamtlsContext)
if err != nil {
return nil, nil, errors.New("internal Error while marshalling the upstream TLS Context")
Expand Down Expand Up @@ -574,6 +578,40 @@ func processEndpoints(clusterName string, clusterDetails *model.EndpointCluster,
}
conf, _ := config.ReadConfigs()

httpProtocolOptions := &upstreams_http_v3.HttpProtocolOptions{
UpstreamProtocolOptions: &upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig_{
ExplicitHttpConfig: &upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig{
ProtocolConfig: &upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig_HttpProtocolOptions{
HttpProtocolOptions: &corev3.Http1ProtocolOptions{
EnableTrailers: config.GetWireLogConfig().LogTrailersEnabled,
},
},
},
},
}

if clusterDetails.HTTP2BackendEnabled {
httpProtocolOptions.UpstreamProtocolOptions = &upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig_{
Amila-Rukshan marked this conversation as resolved.
Show resolved Hide resolved
ExplicitHttpConfig: &upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig{
ProtocolConfig: &upstreams_http_v3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{
Http2ProtocolOptions: &corev3.Http2ProtocolOptions{
HpackTableSize: &wrapperspb.UInt32Value{
Value: conf.Envoy.Upstream.HTTP2.HpackTableSize,
},
MaxConcurrentStreams: &wrapperspb.UInt32Value{
Value: conf.Envoy.Upstream.HTTP2.MaxConcurrentStreams,
},
},
},
},
}
}

ext, err2 := proto.Marshal(httpProtocolOptions)
if err2 != nil {
logger.LoggerOasparser.Error(err2)
}

cluster := clusterv3.Cluster{
Name: clusterName,
ConnectTimeout: durationpb.New(timeout * time.Second),
Expand All @@ -587,8 +625,11 @@ func processEndpoints(clusterName string, clusterDetails *model.EndpointCluster,
TransportSocketMatches: transportSocketMatches,
DnsRefreshRate: durationpb.New(time.Duration(conf.Envoy.Upstream.DNS.DNSRefreshRate) * time.Millisecond),
RespectDnsTtl: conf.Envoy.Upstream.DNS.RespectDNSTtl,
HttpProtocolOptions: &corev3.Http1ProtocolOptions{
EnableTrailers: config.GetWireLogConfig().LogTrailersEnabled,
TypedExtensionProtocolOptions: map[string]*anypb.Any{
"envoy.extensions.upstreams.http.v3.HttpProtocolOptions": &any.Any{
TypeUrl: "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions",
Value: ext,
},
},
}

Expand Down Expand Up @@ -648,7 +689,7 @@ func createHealthCheck() []*corev3.HealthCheck {
}
}

func createUpstreamTLSContext(upstreamCerts []byte, address *corev3.Address) *tlsv3.UpstreamTlsContext {
func createUpstreamTLSContext(upstreamCerts []byte, address *corev3.Address, hTTP2BackendEnabled bool) *tlsv3.UpstreamTlsContext {
conf, errReadConfig := config.ReadConfigs()
//TODO: (VirajSalaka) Error Handling
if errReadConfig != nil {
Expand All @@ -673,6 +714,10 @@ func createUpstreamTLSContext(upstreamCerts []byte, address *corev3.Address) *tl
},
}

if hTTP2BackendEnabled {
upstreamTLSContext.CommonTlsContext.AlpnProtocols = []string{"h2", "http/1.1"}
VirajSalaka marked this conversation as resolved.
Show resolved Hide resolved
}

sanType := tlsv3.SubjectAltNameMatcher_IP_ADDRESS
// Sni should be assigned when there is a hostname
if net.ParseIP(address.GetSocketAddress().GetAddress()) == nil {
Expand Down
12 changes: 12 additions & 0 deletions adapter/internal/oasparser/model/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ func getXWso2Basepath(vendorExtensions map[string]interface{}) string {
return xWso2basepath
}

// getXWso2HTTP2BackendEnabled extracts the value of XWso2HTTP2BackendEnabled extension.
// if the property is not available, false is returned.
func getXWso2HTTP2BackendEnabled(vendorExtensions map[string]interface{}) bool {
xWso2HTTP2BackendEnabled := false
if y, found := vendorExtensions[constants.XWso2HTTP2BackendEnabled]; found {
if val, ok := y.(bool); ok {
xWso2HTTP2BackendEnabled = val
}
}
return xWso2HTTP2BackendEnabled
}

// ResolveThrottlingTier extracts the value of x-wso2-throttling-tier and
// x-throttling-tier extension. if x-wso2-throttling-tier is available it
// will be prioritized.
Expand Down
14 changes: 14 additions & 0 deletions adapter/internal/oasparser/model/mgw_swagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type MgwSwagger struct {
xWso2Endpoints map[string]*EndpointCluster
resources []*Resource
xWso2Basepath string
xWso2HTTP2BackendEnabled bool
xWso2Cors *CorsConfig
securityScheme []SecurityScheme
security []map[string][]string
Expand All @@ -83,6 +84,8 @@ type EndpointCluster struct {
EndpointType string
Config *EndpointConfig
SecurityConfig EndpointSecurity
// Is http2 protocol enabled
HTTP2BackendEnabled bool
}

// Endpoint represents the structure of an endpoint.
Expand Down Expand Up @@ -195,6 +198,11 @@ func (swagger *MgwSwagger) GetXWso2Basepath() string {
return swagger.xWso2Basepath
}

// GetXWso2HTTP2BackendEnabled returns the http2 backend enabled set via the vendor extension.
func (swagger *MgwSwagger) GetXWso2HTTP2BackendEnabled() bool {
return swagger.xWso2HTTP2BackendEnabled
}

// GetVendorExtensions returns the map of vendor extensions which are defined
// at openAPI's root level.
func (swagger *MgwSwagger) GetVendorExtensions() map[string]interface{} {
Expand Down Expand Up @@ -486,6 +494,7 @@ func (swagger *MgwSwagger) SetXWso2Extensions() error {
swagger.setXWso2ThrottlingTier()
swagger.setDisableSecurity()
swagger.setXWso2AuthHeader()
swagger.setXWso2HTTP2BackendEnabled()

// Error nil for successful execution
return nil
Expand Down Expand Up @@ -958,6 +967,11 @@ func (swagger *MgwSwagger) setXWso2Basepath() {
}
}

func (swagger *MgwSwagger) setXWso2HTTP2BackendEnabled() {
extHTTP2BackendEnabled := getXWso2HTTP2BackendEnabled(swagger.vendorExtensions)
swagger.xWso2HTTP2BackendEnabled = extHTTP2BackendEnabled
}

func (swagger *MgwSwagger) setXWso2Cors() {
if cors, corsFound := swagger.vendorExtensions[constants.XWso2Cors]; corsFound {
logger.LoggerOasparser.Debugf("%v configuration is available", constants.XWso2Cors)
Expand Down
4 changes: 4 additions & 0 deletions integration/mock-backend-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http2</artifactId>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ public class Constants {
public static final int INTERCEPTOR_STATUS_SERVER_PORT = 2370;
public static final int MTLS_INTERCEPTOR_HANDLER_SERVER_PORT = 2371;
public static final int WEBSOCKET_SERVER_PORT = 2360;

public static final int MOCK_BACKEND_HTTP2_SERVER_CLEAR_TEXT_PORT = 2350;
public static final int MOCK_BACKEND_HTTP2_SERVER_SECURED_PORT = 2351;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.wso2.choreo.connect.mockbackend;

import org.wso2.choreo.connect.mockbackend.async.MockAsyncServer;
import org.wso2.choreo.connect.mockbackend.http2.Http2MockBackend;

import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -55,5 +56,17 @@ public static void main(String[] args) {
MockAsyncServer mockAsyncServer = new MockAsyncServer(Constants.WEBSOCKET_SERVER_PORT);
mockAsyncServer.start();
}

if(argList.contains("-http2-server-enabled")){
// clear text server
Http2MockBackend http2BackendProdClearText = new Http2MockBackend(Constants.MOCK_BACKEND_HTTP2_SERVER_CLEAR_TEXT_PORT, false, false);
http2BackendProdClearText.startServer();
}

if(argList.contains("-http2-tls-server-enabled")){
// secured server
Http2MockBackend http2BackendProdTLS = new Http2MockBackend(Constants.MOCK_BACKEND_HTTP2_SERVER_SECURED_PORT, true, false);
http2BackendProdTLS.startServer();
}
}
}
Loading