Browse Source
Merge pull request #36 from mutantmonkey/csp
Merge pull request #36 from mutantmonkey/csp
Add support for Content-Security-Policy and X-Frame-Optionspull/40/head
Andrei Marcu
9 years ago
18 changed files with 277 additions and 99 deletions
-
40csp.go
-
38csp_test.go
-
2fileserve.go
-
34server.go
-
74static/css/linx.css
-
18static/js/bin.js
-
2static/js/bin_hljs.js
-
89static/js/upload.js
-
2templates/404.html
-
6templates/display/audio.html
-
36templates/display/bin.html
-
4templates/display/file.html
-
2templates/display/image.html
-
5templates/display/pdf.html
-
10templates/display/video.html
-
6templates/index.html
-
2templates/oops.html
-
6templates/paste.html
@ -0,0 +1,40 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"net/http" |
||||
|
) |
||||
|
|
||||
|
const ( |
||||
|
cspHeader = "Content-Security-Policy" |
||||
|
frameOptionsHeader = "X-Frame-Options" |
||||
|
) |
||||
|
|
||||
|
type csp struct { |
||||
|
h http.Handler |
||||
|
opts CSPOptions |
||||
|
} |
||||
|
|
||||
|
type CSPOptions struct { |
||||
|
policy string |
||||
|
frame string |
||||
|
} |
||||
|
|
||||
|
func (c csp) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
||||
|
// only add a CSP if one is not already set
|
||||
|
if existing := w.Header().Get(cspHeader); existing == "" { |
||||
|
w.Header().Add(cspHeader, c.opts.policy) |
||||
|
} |
||||
|
|
||||
|
w.Header().Set(frameOptionsHeader, c.opts.frame) |
||||
|
|
||||
|
c.h.ServeHTTP(w, r) |
||||
|
} |
||||
|
|
||||
|
func ContentSecurityPolicy(o CSPOptions) func(http.Handler) http.Handler { |
||||
|
fn := func(h http.Handler) http.Handler { |
||||
|
return csp{h, o} |
||||
|
} |
||||
|
return fn |
||||
|
} |
||||
|
|
||||
|
// vim:set ts=8 sw=8 noet:
|
@ -0,0 +1,38 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"net/http" |
||||
|
"net/http/httptest" |
||||
|
"testing" |
||||
|
|
||||
|
"github.com/zenazn/goji" |
||||
|
) |
||||
|
|
||||
|
var testCSPHeaders = map[string]string{ |
||||
|
"Content-Security-Policy": "default-src 'none'; style-src 'self';", |
||||
|
"X-Frame-Options": "SAMEORIGIN", |
||||
|
} |
||||
|
|
||||
|
func TestContentSecurityPolicy(t *testing.T) { |
||||
|
w := httptest.NewRecorder() |
||||
|
|
||||
|
req, err := http.NewRequest("GET", "/", nil) |
||||
|
if err != nil { |
||||
|
t.Fatal(err) |
||||
|
} |
||||
|
|
||||
|
goji.Use(ContentSecurityPolicy(CSPOptions{ |
||||
|
policy: testCSPHeaders["Content-Security-Policy"], |
||||
|
frame: testCSPHeaders["X-Frame-Options"], |
||||
|
})) |
||||
|
|
||||
|
goji.DefaultMux.ServeHTTP(w, req) |
||||
|
|
||||
|
for k, v := range testCSPHeaders { |
||||
|
if w.HeaderMap[k][0] != v { |
||||
|
t.Fatalf("%s header did not match expected value set by middleware", k) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// vim:set ts=8 sw=8 noet:
|
@ -0,0 +1,2 @@ |
|||||
|
hljs.tabReplace = ' '; |
||||
|
hljs.initHighlightingOnLoad(); |
@ -1,5 +1,5 @@ |
|||||
{% extends "base.html" %} |
{% extends "base.html" %} |
||||
|
|
||||
{% block content %} |
{% block content %} |
||||
<a href="/"><img style="border:0;" src='/static/images/404.jpg' width='400'></a> |
|
||||
|
<a href="/"><img src='/static/images/404.jpg'></a> |
||||
{% endblock %} |
{% endblock %} |
@ -1,9 +1,9 @@ |
|||||
{% extends "base.html" %} |
{% extends "base.html" %} |
||||
|
|
||||
{% block main %} |
{% block main %} |
||||
<audio controls style='width: 500px;' preload='auto'> |
|
||||
<source src='/selif/{{ filename }}'> |
|
||||
<a href='/selif/{{ filename }}'>Download it instead</a> |
|
||||
|
<audio class="display-audio" controls preload='auto'> |
||||
|
<source src='/selif/{{ filename }}'> |
||||
|
<a href='/selif/{{ filename }}'>Download it instead</a> |
||||
</audio> |
</audio> |
||||
{% endblock %} |
{% endblock %} |
||||
|
|
@ -1,7 +1,7 @@ |
|||||
{% extends "base.html" %} |
{% extends "base.html" %} |
||||
|
|
||||
{% block main %} |
{% block main %} |
||||
<div class="normal" style="width: 500px;"> |
|
||||
<p class="center">You are requesting <a href="/selif/{{ filename }}">{{ filename }}</a>, <a href="/selif/{{ filename }}">click here</a> to download.</p> |
|
||||
|
<div class="normal display-file"> |
||||
|
<p class="center">You are requesting <a href="/selif/{{ filename }}">{{ filename }}</a>, <a href="/selif/{{ filename }}">click here</a> to download.</p> |
||||
</div> |
</div> |
||||
{% endblock %} |
{% endblock %} |
@ -1,10 +1,8 @@ |
|||||
{% extends "base.html" %} |
{% extends "base.html" %} |
||||
|
|
||||
{% block main %} |
{% block main %} |
||||
<div id='video'> |
|
||||
<video controls autoplay width="800"> |
|
||||
<source src="/selif/{{ filename }}"/> |
|
||||
</video> |
|
||||
</div> |
|
||||
|
|
||||
|
<video class="display-video" controls autoplay> |
||||
|
<source src="/selif/{{ filename }}"/> |
||||
|
<a href='/selif/{{ filename }}'>Download it instead</a> |
||||
|
</video> |
||||
{% endblock %} |
{% endblock %} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue