Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-dms3-cmds
Commits
df28dcfc
Commit
df28dcfc
authored
May 07, 2015
by
David Braun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add CORS middleware handler to the API.
parent
a586024e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
108 additions
and
13 deletions
+108
-13
http/handler.go
http/handler.go
+37
-13
http/handler_test.go
http/handler_test.go
+71
-0
No files found.
http/handler.go
View file @
df28dcfc
...
...
@@ -8,6 +8,8 @@ import (
"strconv"
"strings"
"github.com/rs/cors"
context
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
cmds
"github.com/ipfs/go-ipfs/commands"
...
...
@@ -16,10 +18,17 @@ import (
var
log
=
u
.
Logger
(
"commands/http"
)
// the internal handler for the API
type
internalHandler
struct
{
ctx
cmds
.
Context
root
*
cmds
.
Command
}
// The Handler struct is funny because we want to wrap our internal handler
// with CORS while keeping our fields.
type
Handler
struct
{
ctx
cmds
.
Context
root
*
cmds
.
Command
origin
string
internalHandler
corsHandler
http
.
Handler
}
var
ErrNotFound
=
errors
.
New
(
"404 page not found"
)
...
...
@@ -39,16 +48,31 @@ var mimeTypes = map[string]string{
cmds
.
Text
:
"text/plain"
,
}
func
NewHandler
(
ctx
cmds
.
Context
,
root
*
cmds
.
Command
,
o
rigin
string
)
*
Handler
{
func
NewHandler
(
ctx
cmds
.
Context
,
root
*
cmds
.
Command
,
allowedO
rigin
string
)
*
Handler
{
// allow whitelisted origins (so we can make API requests from the browser)
if
len
(
o
rigin
)
>
0
{
log
.
Info
(
"Allowing API requests from origin: "
+
o
rigin
)
if
len
(
allowedO
rigin
)
>
0
{
log
.
Info
(
"Allowing API requests from origin: "
+
allowedO
rigin
)
}
return
&
Handler
{
ctx
,
root
,
origin
}
// Create a handler for the API.
internal
:=
internalHandler
{
ctx
,
root
}
// Create a CORS object for wrapping the internal handler.
c
:=
cors
.
New
(
cors
.
Options
{
AllowedMethods
:
[]
string
{
"GET"
,
"POST"
,
"PUT"
},
// use AllowOriginFunc instead of AllowedOrigins because we want to be
// restrictive by default.
AllowOriginFunc
:
func
(
origin
string
)
bool
{
return
(
allowedOrigin
==
"*"
)
||
(
origin
==
allowedOrigin
)
},
})
// Wrap the internal handler with CORS handling-middleware.
return
&
Handler
{
internal
,
c
.
Handler
(
internal
)}
}
func
(
i
Handler
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
(
i
internal
Handler
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
log
.
Debug
(
"Incoming API request: "
,
r
.
URL
)
// error on external referers (to prevent CSRF attacks)
...
...
@@ -65,11 +89,6 @@ func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
if
len
(
i
.
origin
)
>
0
{
w
.
Header
()
.
Set
(
"Access-Control-Allow-Origin"
,
i
.
origin
)
}
w
.
Header
()
.
Set
(
"Access-Control-Allow-Headers"
,
"Content-Type"
)
req
,
err
:=
Parse
(
r
,
i
.
root
)
if
err
!=
nil
{
if
err
==
ErrNotFound
{
...
...
@@ -168,6 +187,11 @@ func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
flushCopy
(
w
,
out
)
}
func
(
i
Handler
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
// Call the CORS handler which wraps the internal handler.
i
.
corsHandler
.
ServeHTTP
(
w
,
r
)
}
// flushCopy Copies from an io.Reader to a http.ResponseWriter.
// Flushes chunks over HTTP stream as they are read (if supported by transport).
func
flushCopy
(
w
http
.
ResponseWriter
,
out
io
.
Reader
)
error
{
...
...
http/handler_test.go
0 → 100644
View file @
df28dcfc
package
http
import
(
"net/http"
"net/http/httptest"
"testing"
"github.com/ipfs/go-ipfs/commands"
)
func
assertHeaders
(
t
*
testing
.
T
,
resHeaders
http
.
Header
,
reqHeaders
map
[
string
]
string
)
{
for
name
,
value
:=
range
reqHeaders
{
if
resHeaders
.
Get
(
name
)
!=
value
{
t
.
Errorf
(
"Invalid header `%s', wanted `%s', got `%s'"
,
name
,
value
,
resHeaders
.
Get
(
name
))
}
}
}
func
TestDisallowedOrigin
(
t
*
testing
.
T
)
{
res
:=
httptest
.
NewRecorder
()
req
,
_
:=
http
.
NewRequest
(
"GET"
,
"http://example.com/foo"
,
nil
)
req
.
Header
.
Add
(
"Origin"
,
"http://barbaz.com"
)
handler
:=
NewHandler
(
commands
.
Context
{},
nil
,
""
)
handler
.
ServeHTTP
(
res
,
req
)
assertHeaders
(
t
,
res
.
Header
(),
map
[
string
]
string
{
"Access-Control-Allow-Origin"
:
""
,
"Access-Control-Allow-Methods"
:
""
,
"Access-Control-Allow-Credentials"
:
""
,
"Access-Control-Max-Age"
:
""
,
"Access-Control-Expose-Headers"
:
""
,
})
}
func
TestWildcardOrigin
(
t
*
testing
.
T
)
{
res
:=
httptest
.
NewRecorder
()
req
,
_
:=
http
.
NewRequest
(
"GET"
,
"http://example.com/foo"
,
nil
)
req
.
Header
.
Add
(
"Origin"
,
"http://foobar.com"
)
handler
:=
NewHandler
(
commands
.
Context
{},
nil
,
"*"
)
handler
.
ServeHTTP
(
res
,
req
)
assertHeaders
(
t
,
res
.
Header
(),
map
[
string
]
string
{
"Access-Control-Allow-Origin"
:
"http://foobar.com"
,
"Access-Control-Allow-Methods"
:
""
,
"Access-Control-Allow-Headers"
:
""
,
"Access-Control-Allow-Credentials"
:
""
,
"Access-Control-Max-Age"
:
""
,
"Access-Control-Expose-Headers"
:
""
,
})
}
func
TestAllowedMethod
(
t
*
testing
.
T
)
{
res
:=
httptest
.
NewRecorder
()
req
,
_
:=
http
.
NewRequest
(
"OPTIONS"
,
"http://example.com/foo"
,
nil
)
req
.
Header
.
Add
(
"Origin"
,
"http://www.foobar.com"
)
req
.
Header
.
Add
(
"Access-Control-Request-Method"
,
"PUT"
)
handler
:=
NewHandler
(
commands
.
Context
{},
nil
,
"http://www.foobar.com"
)
handler
.
ServeHTTP
(
res
,
req
)
assertHeaders
(
t
,
res
.
Header
(),
map
[
string
]
string
{
"Access-Control-Allow-Origin"
:
"http://www.foobar.com"
,
"Access-Control-Allow-Methods"
:
"PUT"
,
"Access-Control-Allow-Headers"
:
""
,
"Access-Control-Allow-Credentials"
:
""
,
"Access-Control-Max-Age"
:
""
,
"Access-Control-Expose-Headers"
:
""
,
})
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment