diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 907bdabf3..effa011fd 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -806,6 +806,12 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e return nil, fmt.Errorf("serveHTTPGateway: ConstructNode() failed: %s", err) } + if len(listeners) > 0 { + if err := node.Repo.SetGatewayAddr(listeners[0].Addr()); err != nil { + return nil, fmt.Errorf("serveHTTPGateway: SetGatewayAddr() failed: %w", err) + } + } + errc := make(chan error) var wg sync.WaitGroup for _, lis := range listeners { diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index cbe1a3113..cc11769bb 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "net" "os" "path/filepath" "strings" @@ -63,6 +64,7 @@ func (err NoRepoError) Error() string { } const apiFile = "api" +const gatewayFile = "gateway" const swarmKeyFile = "swarm.key" const specFn = "datastore_spec" @@ -387,6 +389,44 @@ func (r *FSRepo) SetAPIAddr(addr ma.Multiaddr) error { return err } +// SetGatewayAddr writes the Gateway Addr to the /gateway file. +func (r *FSRepo) SetGatewayAddr(addr net.Addr) error { + // Create a temp file to write the address, so that we don't leave empty file when the + // program crashes after creating the file. + tmpPath := filepath.Join(r.path, "."+gatewayFile+".tmp") + f, err := os.Create(tmpPath) + if err != nil { + return err + } + var good bool + // Silently remove as worst last case with defers. + defer func() { + if !good { + os.Remove(tmpPath) + } + }() + defer f.Close() + + if _, err := fmt.Fprintf(f, "http://%s", addr.String()); err != nil { + return err + } + if err := f.Close(); err != nil { + return err + } + + // Atomically rename the temp file to the correct file name. + err = os.Rename(tmpPath, filepath.Join(r.path, gatewayFile)) + good = err == nil + if good { + return nil + } + // Remove the temp file when rename return error + if err1 := os.Remove(tmpPath); err1 != nil { + return fmt.Errorf("File Rename error: %w, File remove error: %s", err, err1.Error()) + } + return err +} + // openConfig returns an error if the config file is not present. func (r *FSRepo) openConfig() error { conf, err := serialize.Load(r.configFilePath) @@ -474,6 +514,11 @@ func (r *FSRepo) Close() error { log.Warn("error removing api file: ", err) } + err = os.Remove(filepath.Join(r.path, gatewayFile)) + if err != nil && !os.IsNotExist(err) { + log.Warn("error removing gateway file: ", err) + } + if err := r.ds.Close(); err != nil { return err } diff --git a/repo/mock.go b/repo/mock.go index f33f64a2c..a50d448ed 100644 --- a/repo/mock.go +++ b/repo/mock.go @@ -3,6 +3,7 @@ package repo import ( "context" "errors" + "net" filestore "github.com/ipfs/go-filestore" keystore "github.com/ipfs/go-ipfs-keystore" @@ -50,6 +51,8 @@ func (m *Mock) Close() error { return m.D.Close() } func (m *Mock) SetAPIAddr(addr ma.Multiaddr) error { return errTODO } +func (m *Mock) SetGatewayAddr(addr net.Addr) error { return errTODO } + func (m *Mock) Keystore() keystore.Keystore { return m.K } func (m *Mock) SwarmKey() ([]byte, error) { diff --git a/repo/repo.go b/repo/repo.go index c301fb393..3c6103177 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -4,6 +4,7 @@ import ( "context" "errors" "io" + "net" filestore "github.com/ipfs/go-filestore" keystore "github.com/ipfs/go-ipfs-keystore" @@ -51,6 +52,9 @@ type Repo interface { // SetAPIAddr sets the API address in the repo. SetAPIAddr(addr ma.Multiaddr) error + // SetGatewayAddr sets the Gateway address in the repo. + SetGatewayAddr(addr net.Addr) error + // SwarmKey returns the configured shared symmetric key for the private networks feature. SwarmKey() ([]byte, error) diff --git a/test/sharness/t0110-gateway.sh b/test/sharness/t0110-gateway.sh index a1e8f2864..484eefe4a 100755 --- a/test/sharness/t0110-gateway.sh +++ b/test/sharness/t0110-gateway.sh @@ -287,6 +287,12 @@ test_expect_success "GET compact blocks succeeds" ' test_cmp expected actual ' +test_expect_success "Verify gateway file" ' + cat "$IPFS_PATH/gateway" >> gateway_file_actual && + echo -n "http://$GWAY_ADDR" >> gateway_daemon_actual && + test_cmp gateway_daemon_actual gateway_file_actual +' + test_kill_ipfs_daemon