@@ -12,6 +12,7 @@ import (
12
12
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
13
13
14
14
cmds "github.com/ipfs/go-ipfs/commands"
15
+ commands "github.com/ipfs/go-ipfs/core/commands"
15
16
u "github.com/ipfs/go-ipfs/util"
16
17
)
17
18
@@ -21,6 +22,7 @@ var log = u.Logger("commands/http")
21
22
type internalHandler struct {
22
23
ctx cmds.Context
23
24
root * cmds.Command
25
+ readOnly bool
24
26
}
25
27
26
28
// The Handler struct is funny because we want to wrap our internal handler
@@ -47,14 +49,18 @@ var mimeTypes = map[string]string{
47
49
cmds .Text : "text/plain" ,
48
50
}
49
51
52
+ var readOnlyCmds = map [* cmds.Command ]bool {
53
+ commands .RefsCmd : true ,
54
+ }
55
+
50
56
func NewHandler (ctx cmds.Context , root * cmds.Command , allowedOrigin string ) * Handler {
51
57
// allow whitelisted origins (so we can make API requests from the browser)
52
58
if len (allowedOrigin ) > 0 {
53
59
log .Info ("Allowing API requests from origin: " + allowedOrigin )
54
60
}
55
61
56
62
// Create a handler for the API.
57
- internal := internalHandler {ctx , root }
63
+ internal := internalHandler {ctx , root , false }
58
64
59
65
// Create a CORS object for wrapping the internal handler.
60
66
c := cors .New (cors.Options {
@@ -71,6 +77,32 @@ func NewHandler(ctx cmds.Context, root *cmds.Command, allowedOrigin string) *Han
71
77
return & Handler {internal , c .Handler (internal )}
72
78
}
73
79
80
+ func NewReadOnlyHandler (ctx cmds.Context , root * cmds.Command , allowedOrigin string ) * Handler {
81
+ // allow whitelisted origins (so we can make API requests from the browser)
82
+ if len (allowedOrigin ) > 0 {
83
+ log .Info ("Allowing API requests from origin: " + allowedOrigin )
84
+ }
85
+
86
+ // Create a handler for the API.
87
+ internal := internalHandler {ctx , root , true }
88
+
89
+ // Create a CORS object for wrapping the internal handler.
90
+ c := cors .New (cors.Options {
91
+ AllowedMethods : []string {"GET" },
92
+
93
+ // use AllowOriginFunc instead of AllowedOrigins because we want to be
94
+ // restrictive by default.
95
+ AllowOriginFunc : func (origin string ) bool {
96
+ return (allowedOrigin == "*" ) || (origin == allowedOrigin )
97
+ },
98
+ })
99
+
100
+ fmt .Println ("Read Only API" )
101
+
102
+ // Wrap the internal handler with CORS handling-middleware.
103
+ return & Handler {internal , c .Handler (internal )}
104
+ }
105
+
74
106
func (i internalHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
75
107
log .Debug ("Incoming API request: " , r .URL )
76
108
@@ -89,6 +121,7 @@ func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
89
121
}
90
122
91
123
req , err := Parse (r , i .root )
124
+
92
125
if err != nil {
93
126
if err == ErrNotFound {
94
127
w .WriteHeader (http .StatusNotFound )
@@ -99,6 +132,15 @@ func (i internalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
99
132
return
100
133
}
101
134
135
+ if i .readOnly == true {
136
+ if _ , ok := readOnlyCmds [req .Command ()]; ! ok {
137
+ // Or a 404?
138
+ w .WriteHeader (http .StatusForbidden )
139
+ w .Write ([]byte ("You may not execute this request on the read-only api." ))
140
+ return
141
+ }
142
+ }
143
+
102
144
// get the node's context to pass into the commands.
103
145
node , err := i .ctx .GetNode ()
104
146
if err != nil {
0 commit comments