1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-05-17 15:06:47 +08:00

feat: Gateway.DeserializedResponses config flag (#9789)

Co-authored-by: Marcin Rataj <lidel@lidel.org>
This commit is contained in:
Henrique Dias
2023-05-30 00:59:34 +02:00
committed by GitHub
parent 38556b8d21
commit c10b804449
10 changed files with 235 additions and 42 deletions

View File

@ -28,22 +28,11 @@ import (
func GatewayOption(paths ...string) ServeOption {
return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
cfg, err := n.Repo.Config()
gwConfig, err := getGatewayConfig(n)
if err != nil {
return nil, err
}
headers := make(map[string][]string, len(cfg.Gateway.HTTPHeaders))
for h, v := range cfg.Gateway.HTTPHeaders {
headers[http.CanonicalHeaderKey(h)] = v
}
gateway.AddAccessControlHeaders(headers)
gwConfig := gateway.Config{
Headers: headers,
}
gwAPI, err := newGatewayBackend(n)
if err != nil {
return nil, err
@ -65,7 +54,7 @@ func GatewayOption(paths ...string) ServeOption {
func HostnameOption() ServeOption {
return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
cfg, err := n.Repo.Config()
gwConfig, err := getGatewayConfig(n)
if err != nil {
return nil, err
}
@ -75,9 +64,8 @@ func HostnameOption() ServeOption {
return nil, err
}
publicGateways := convertPublicGateways(cfg.Gateway.PublicGateways)
childMux := http.NewServeMux()
mux.HandleFunc("/", gateway.WithHostname(childMux, gwAPI, publicGateways, cfg.Gateway.NoDNSLink).ServeHTTP)
mux.HandleFunc("/", gateway.WithHostname(gwConfig, gwAPI, childMux).ServeHTTP)
return childMux, nil
}
}
@ -212,30 +200,49 @@ var defaultKnownGateways = map[string]*gateway.Specification{
"localhost": subdomainGatewaySpec,
}
func convertPublicGateways(publicGateways map[string]*config.GatewaySpec) map[string]*gateway.Specification {
gws := map[string]*gateway.Specification{}
// First, implicit defaults such as subdomain gateway on localhost
for hostname, gw := range defaultKnownGateways {
gws[hostname] = gw
func getGatewayConfig(n *core.IpfsNode) (gateway.Config, error) {
cfg, err := n.Repo.Config()
if err != nil {
return gateway.Config{}, err
}
// Then apply values from Gateway.PublicGateways, if present in the config
for hostname, gw := range publicGateways {
// Parse configuration headers and add the default Access Control Headers.
headers := make(map[string][]string, len(cfg.Gateway.HTTPHeaders))
for h, v := range cfg.Gateway.HTTPHeaders {
headers[http.CanonicalHeaderKey(h)] = v
}
gateway.AddAccessControlHeaders(headers)
// Initialize gateway configuration, with empty PublicGateways, handled after.
gwCfg := gateway.Config{
Headers: headers,
DeserializedResponses: cfg.Gateway.DeserializedResponses.WithDefault(config.DefaultDeserializedResponses),
NoDNSLink: cfg.Gateway.NoDNSLink,
PublicGateways: map[string]*gateway.Specification{},
}
// Add default implicit known gateways, such as subdomain gateway on localhost.
for hostname, gw := range defaultKnownGateways {
gwCfg.PublicGateways[hostname] = gw
}
// Apply values from cfg.Gateway.PublicGateways if they exist.
for hostname, gw := range cfg.Gateway.PublicGateways {
if gw == nil {
// Remove any implicit defaults, if present. This is useful when one
// wants to disable subdomain gateway on localhost etc.
delete(gws, hostname)
// wants to disable subdomain gateway on localhost, etc.
delete(gwCfg.PublicGateways, hostname)
continue
}
gws[hostname] = &gateway.Specification{
Paths: gw.Paths,
NoDNSLink: gw.NoDNSLink,
UseSubdomains: gw.UseSubdomains,
InlineDNSLink: gw.InlineDNSLink.WithDefault(config.DefaultInlineDNSLink),
gwCfg.PublicGateways[hostname] = &gateway.Specification{
Paths: gw.Paths,
NoDNSLink: gw.NoDNSLink,
UseSubdomains: gw.UseSubdomains,
InlineDNSLink: gw.InlineDNSLink.WithDefault(config.DefaultInlineDNSLink),
DeserializedResponses: gw.DeserializedResponses.WithDefault(gwCfg.DeserializedResponses),
}
}
return gws
return gwCfg, nil
}

View File

@ -14,6 +14,7 @@ import (
core "github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/coreapi"
repo "github.com/ipfs/kubo/repo"
"github.com/stretchr/testify/assert"
iface "github.com/ipfs/boxo/coreiface"
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
@ -173,3 +174,42 @@ func TestVersion(t *testing.T) {
t.Fatalf("response doesn't contain protocol version:\n%s", s)
}
}
func TestDeserializedResponsesInheritance(t *testing.T) {
for _, testCase := range []struct {
globalSetting config.Flag
gatewaySetting config.Flag
expectedGatewaySetting bool
}{
{config.True, config.Default, true},
{config.False, config.Default, false},
{config.False, config.True, true},
{config.True, config.False, false},
} {
c := config.Config{
Identity: config.Identity{
PeerID: "QmTFauExutTsy4XP6JbMFcw2Wa9645HJt2bTqL6qYDCKfe", // required by offline node
},
Gateway: config.Gateway{
DeserializedResponses: testCase.globalSetting,
PublicGateways: map[string]*config.GatewaySpec{
"example.com": {
DeserializedResponses: testCase.gatewaySetting,
},
},
},
}
r := &repo.Mock{
C: c,
D: syncds.MutexWrap(datastore.NewMapDatastore()),
}
n, err := core.NewNode(context.Background(), &core.BuildCfg{Repo: r})
assert.NoError(t, err)
gwCfg, err := getGatewayConfig(n)
assert.NoError(t, err)
assert.Contains(t, gwCfg.PublicGateways, "example.com")
assert.Equal(t, testCase.expectedGatewaySetting, gwCfg.PublicGateways["example.com"].DeserializedResponses)
}
}