From b2fadffc5e6d593fc314ce8507017b267a7fe928 Mon Sep 17 00:00:00 2001 From: Mark Gaiser Date: Sun, 31 Jul 2022 15:16:05 +0200 Subject: [PATCH 1/7] feat: add gateway file The file contains the gateway your node is hosting in the http://: format. Structurally it works exactly the same as the API file. --- cmd/ipfs/daemon.go | 4 ++++ repo/fsrepo/fsrepo.go | 36 ++++++++++++++++++++++++++++++++++++ repo/mock.go | 3 +++ repo/repo.go | 4 ++++ 4 files changed, 47 insertions(+) diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 907bdabf3a9..0f6b22e368c 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -806,6 +806,10 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e return nil, fmt.Errorf("serveHTTPGateway: ConstructNode() failed: %s", err) } + if err := node.Repo.SetGatewayAddr(listeners[0].Addr()); err != nil { + return nil, fmt.Errorf("serveHTTPGateway: SetGatewayAddr() failed: %s", 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 cbe1a31137c..33690e5ea5f 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" "sync" + "net" filestore "github.com/ipfs/go-filestore" keystore "github.com/ipfs/go-ipfs-keystore" @@ -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,35 @@ 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. + f, err := os.Create(filepath.Join(r.path, "."+gatewayFile+".tmp")) + if err != nil { + return err + } + + 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. + if err = os.Rename(filepath.Join(r.path, "."+gatewayFile+".tmp"), filepath.Join(r.path, + gatewayFile)); err == nil { + return nil + } + // Remove the temp file when rename return error + if err1 := os.Remove(filepath.Join(r.path, "."+gatewayFile+".tmp")); err1 != nil { + return fmt.Errorf("File Rename error: %s, File remove error: %s", err.Error(), + 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 +505,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 f33f64a2cc1..a50d448ed02 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 c301fb39307..3c61031774b 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) From bad1e17ad81287bfe7e9f79ab7f45a94ef594159 Mon Sep 17 00:00:00 2001 From: Mark Gaiser Date: Sun, 31 Jul 2022 22:31:12 +0200 Subject: [PATCH 2/7] fix review feedback --- cmd/ipfs/daemon.go | 2 +- repo/fsrepo/fsrepo.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 0f6b22e368c..5414c998ae5 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -807,7 +807,7 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e } if err := node.Repo.SetGatewayAddr(listeners[0].Addr()); err != nil { - return nil, fmt.Errorf("serveHTTPGateway: SetGatewayAddr() failed: %s", err) + return nil, fmt.Errorf("serveHTTPGateway: SetGatewayAddr() failed: %w", err) } errc := make(chan error) diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 33690e5ea5f..d991d0f97f2 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -5,11 +5,11 @@ import ( "errors" "fmt" "io" + "net" "os" "path/filepath" "strings" "sync" - "net" filestore "github.com/ipfs/go-filestore" keystore "github.com/ipfs/go-ipfs-keystore" @@ -398,7 +398,7 @@ func (r *FSRepo) SetGatewayAddr(addr net.Addr) error { return err } - if _, err = fmt.Fprintf(f, "http://%s", addr.String()); err != nil { + if _, err := fmt.Fprintf(f, "http://%s", addr.String()); err != nil { return err } if err = f.Close(); err != nil { From fa0aaa5ec240c5ed9058a472f7b84df63ca0ec05 Mon Sep 17 00:00:00 2001 From: Mark Gaiser Date: Mon, 1 Aug 2022 13:15:45 +0200 Subject: [PATCH 3/7] Update repo/fsrepo/fsrepo.go Co-authored-by: Jorropo --- repo/fsrepo/fsrepo.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index d991d0f97f2..50570fe0cdb 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -393,27 +393,34 @@ func (r *FSRepo) SetAPIAddr(addr ma.Multiaddr) error { 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. - f, err := os.Create(filepath.Join(r.path, "."+gatewayFile+".tmp")) + 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 { + if err := f.Close(); err != nil { return err } // Atomically rename the temp file to the correct file name. - if err = os.Rename(filepath.Join(r.path, "."+gatewayFile+".tmp"), filepath.Join(r.path, - gatewayFile)); err == nil { + 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(filepath.Join(r.path, "."+gatewayFile+".tmp")); err1 != nil { - return fmt.Errorf("File Rename error: %s, File remove error: %s", err.Error(), - err1.Error()) + if err1 := os.Remove(tmpPath); err1 != nil { + return fmt.Errorf("File Rename error: %w, File remove error: %s", err.Error(), err1.Error()) } return err } From b19aa2c7403e30e24b1eb7c646bebdeaf4f0e658 Mon Sep 17 00:00:00 2001 From: Mark Gaiser Date: Mon, 1 Aug 2022 13:23:47 +0200 Subject: [PATCH 4/7] Update repo/fsrepo/fsrepo.go Co-authored-by: Jorropo --- repo/fsrepo/fsrepo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 50570fe0cdb..4427a444d2e 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -420,7 +420,7 @@ func (r *FSRepo) SetGatewayAddr(addr net.Addr) error { } // 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.Error(), err1.Error()) + return fmt.Errorf("File Rename error: %w, File remove error: %s", err, err1.Error()) } return err } From 5f6e9ca265fb8ef8f3af906c0c093b86fcd4b469 Mon Sep 17 00:00:00 2001 From: Mark Gaiser Date: Mon, 1 Aug 2022 13:23:28 +0200 Subject: [PATCH 5/7] Fix formatting --- repo/fsrepo/fsrepo.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/repo/fsrepo/fsrepo.go b/repo/fsrepo/fsrepo.go index 4427a444d2e..cc11769bbae 100644 --- a/repo/fsrepo/fsrepo.go +++ b/repo/fsrepo/fsrepo.go @@ -401,7 +401,9 @@ func (r *FSRepo) SetGatewayAddr(addr net.Addr) error { var good bool // Silently remove as worst last case with defers. defer func() { - if !good { os.Remove(tmpPath) } + if !good { + os.Remove(tmpPath) + } }() defer f.Close() From 613a3b997767862c788bba94fd2d712c42d2a6b2 Mon Sep 17 00:00:00 2001 From: Mark Gaiser Date: Wed, 3 Aug 2022 00:06:36 +0200 Subject: [PATCH 6/7] check for listener array length --- cmd/ipfs/daemon.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index 5414c998ae5..effa011fd4b 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -806,8 +806,10 @@ func serveHTTPGateway(req *cmds.Request, cctx *oldcmds.Context) (<-chan error, e return nil, fmt.Errorf("serveHTTPGateway: ConstructNode() failed: %s", err) } - if err := node.Repo.SetGatewayAddr(listeners[0].Addr()); err != nil { - return nil, fmt.Errorf("serveHTTPGateway: SetGatewayAddr() failed: %w", 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) From 3b481bc19d38043d96390aaaae86dcdfb87db218 Mon Sep 17 00:00:00 2001 From: Mark Gaiser Date: Mon, 8 Aug 2022 00:17:51 +0200 Subject: [PATCH 7/7] add testcase --- test/sharness/t0110-gateway.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/sharness/t0110-gateway.sh b/test/sharness/t0110-gateway.sh index a1e8f286491..484eefe4a0d 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