Make gateway read-only by default and add option to make it writable
Mildred Ki'Lya committed
Jan 28, 2015 at 12:57 UTC
7d09da3c8b0b5d2dd2cf0d357cb4976093fafa92
7 files changed
+49
-20
cmd/ipfs-gateway-fs/main.go
+2
-1
@@ -17,6 +17,7 @@ import (
17
)
18
19
var (
20
+ writable = flag.Bool("writable", false, "enable writing objects (with POST, PUT and DELETE)")
21
refreshAssetsInterval = flag.Duration("refresh-assets-interval", 30*time.Second, "refresh assets")
22
garbageCollectInterval = flag.Duration("gc-interval", 24*time.Hour, "frequency of repo garbage collection")
23
assetsPath = flag.String("assets-path", "", "if provided, periodically adds contents of path to IPFS")
@@ -93,7 +94,7 @@ func run() error {
94
}
95
96
opts := []corehttp.ServeOption{
96
- corehttp.GatewayOption,
97
+ corehttp.GatewayOption(*writable),
98
}
99
if err := corehttp.ListenAndServe(node, *host, opts...); err != nil {
100
return err
cmd/ipfs/daemon.go
+18
-2
@@ -2,6 +2,7 @@ package main
2
3
import (
4
"bytes"
5
+ "fmt"
6
7
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8
cmds "github.com/jbenet/go-ipfs/commands"
@@ -15,6 +16,7 @@ import (
16
const (
17
initOptionKwd = "init"
18
mountKwd = "mount"
19
+ writableKwd = "writable"
20
ipfsMountKwd = "mount-ipfs"
21
ipnsMountKwd = "mount-ipns"
22
// apiAddrKwd = "address-api"
@@ -36,6 +38,7 @@ the daemon.
38
Options: []cmds.Option{
39
cmds.BoolOption(initOptionKwd, "Initialize IPFS with default settings if not already initialized"),
40
cmds.BoolOption(mountKwd, "Mounts IPFS to the filesystem"),
41
+ cmds.BoolOption(writableKwd, "Enable writing objects (with POST, PUT and DELETE)"),
42
cmds.StringOption(ipfsMountKwd, "Path to the mountpoint for IPFS (if using --mount)"),
43
cmds.StringOption(ipnsMountKwd, "Path to the mountpoint for IPNS (if using --mount)"),
44
@@ -161,9 +164,22 @@ func daemonFunc(req cmds.Request, res cmds.Response) {
164
rootRedirect = corehttp.RedirectOption("", cfg.Gateway.RootRedirect)
165
}
166
167
+ writable, writableOptionFound, err := req.Option(writableKwd).Bool()
168
+ if err != nil {
169
+ res.SetError(err, cmds.ErrNormal)
170
+ return
171
+ }
172
+ if !writableOptionFound {
173
+ writable = cfg.Gateway.Writable
174
+ }
175
+
176
+ if writable {
177
+ fmt.Printf("IPNS gateway mounted read-write\n")
178
+ }
179
+
180
if gatewayMaddr != nil {
181
go func() {
166
- var opts = []corehttp.ServeOption{corehttp.GatewayOption}
182
+ var opts = []corehttp.ServeOption{corehttp.GatewayOption(writable)}
183
if rootRedirect != nil {
184
opts = append(opts, rootRedirect)
185
}
@@ -177,7 +193,7 @@ func daemonFunc(req cmds.Request, res cmds.Response) {
193
var opts = []corehttp.ServeOption{
194
corehttp.CommandsOption(*req.Context()),
195
corehttp.WebUIOption,
180
- corehttp.GatewayOption,
196
+ corehttp.GatewayOption(true),
197
}
198
if rootRedirect != nil {
199
opts = append(opts, rootRedirect)
cmd/ipfswatch/main.go
+1
-1
@@ -80,7 +80,7 @@ func run(ipfsPath, watchPath string) error {
80
if *http {
81
addr := "/ip4/127.0.0.1/tcp/5001"
82
var opts = []corehttp.ServeOption{
83
- corehttp.GatewayOption,
83
+ corehttp.GatewayOption(true),
84
corehttp.WebUIOption,
85
corehttp.CommandsOption(cmdCtx(node, ipfsPath)),
86
}
core/corehttp/gateway.go
+9
-7
@@ -6,12 +6,14 @@ import (
6
core "github.com/jbenet/go-ipfs/core"
7
)
8
9
-func GatewayOption(n *core.IpfsNode, mux *http.ServeMux) error {
10
- gateway, err := newGatewayHandler(n)
11
- if err != nil {
12
- return err
13
- }
14
- mux.Handle("/ipfs/", gateway)
9
+func GatewayOption(writable bool) ServeOption {
10
+ return func(n *core.IpfsNode, mux *http.ServeMux) error {
11
+ gateway, err := newGatewayHandler(n, writable)
12
+ if err != nil {
13
+ return err
14
+ }
15
+ mux.Handle("/ipfs/", gateway)
16
mux.Handle("/ipns/", gateway)
16
- return nil
17
+ return nil
18
+ }
19
}
core/corehttp/gateway_handler.go
+17
-9
@@ -48,13 +48,15 @@ type directoryItem struct {
48
// gatewayHandler is a HTTP handler that serves IPFS objects (accessible by default at /ipfs/<path>)
49
// (it serves requests like GET /ipfs/QmVRzPKPzNtSrEzBFm2UZfxmPAgnaLke4DMcerbsGGSaFe/link)
50
type gatewayHandler struct {
51
- node *core.IpfsNode
52
- dirList *template.Template
51
+ node *core.IpfsNode
52
+ dirList *template.Template
53
+ writable bool
54
}
55
55
-func newGatewayHandler(node *core.IpfsNode) (*gatewayHandler, error) {
56
+func newGatewayHandler(node *core.IpfsNode, writable bool) (*gatewayHandler, error) {
57
i := &gatewayHandler{
57
- node: node,
58
+ node: node,
59
+ writable: writable,
60
}
61
err := i.loadTemplate()
62
if err != nil {
@@ -116,17 +118,17 @@ func (i *gatewayHandler) NewDagReader(nd *dag.Node) (uio.ReadSeekCloser, error)
118
}
119
120
func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
119
- if r.Method == "POST" {
121
+ if i.writable && r.Method == "POST" {
122
i.postHandler(w, r)
123
return
124
}
125
124
- if r.Method == "PUT" {
126
+ if i.writable && r.Method == "PUT" {
127
i.putHandler(w, r)
128
return
129
}
130
129
- if r.Method == "DELETE" {
131
+ if i.writable && r.Method == "DELETE" {
132
i.deleteHandler(w, r)
133
return
134
}
@@ -136,8 +138,14 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
138
return
139
}
140
139
- errmsg := "Method " + r.Method + " not allowed: " + "bad request for " + r.URL.Path
140
- w.WriteHeader(http.StatusBadRequest)
141
+ errmsg := "Method " + r.Method + " not allowed: "
142
+ if !i.writable {
143
+ w.WriteHeader(http.StatusMethodNotAllowed)
144
+ errmsg = errmsg + "read only access"
145
+ } else {
146
+ w.WriteHeader(http.StatusBadRequest)
147
+ errmsg = errmsg + "bad request for " + r.URL.Path
148
+ }
149
w.Write([]byte(errmsg))
150
log.Error(errmsg)
151
}
repo/config/gateway.go
+1
@@ -3,4 +3,5 @@ package config
3
// Gateway contains options for the HTTP gateway server.
4
type Gateway struct {
5
RootRedirect string
6
+ Writable bool
7
}
repo/config/init.go
+1
@@ -54,6 +54,7 @@ func Init(out io.Writer, nBitsForKeypair int) (*Config, error) {
54
55
Gateway: Gateway{
56
RootRedirect: "",
57
+ Writable: false,
58
},
59
}
60