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:
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user