HTTP API: server, credential and the list of chats #12
@@ -222,8 +222,9 @@ container.
|
|||||||
starts once set-up is done; if it cannot listen, the bot exits with an
|
starts once set-up is done; if it cannot listen, the bot exits with an
|
||||||
error, as when the chat client fails. Every request must carry the
|
error, as when the chat client fails. Every request must carry the
|
||||||
credential, compared in constant time; every response carries headers
|
credential, compared in constant time; every response carries headers
|
||||||
that forbid framing, content sniffing, caching and referrers; a
|
that forbid framing, content sniffing, caching and referrers, and a
|
||||||
request body is capped at 64 KiB and a request's work at 10 seconds.
|
`Permissions-Policy` that denies the camera, microphone and location;
|
||||||
|
a request body is capped at 64 KiB and a request's work at 10 seconds.
|
||||||
Handlers call the chat client on the request's own goroutine, never on
|
Handlers call the chat client on the request's own goroutine, never on
|
||||||
the one that delivers events, which also delivers the chat client's
|
the one that delivers events, which also delivers the chat client's
|
||||||
answers. When the bot stops, requests in progress get 5 seconds to
|
answers. When the bot stops, requests in progress get 5 seconds to
|
||||||
|
|||||||
+4
-1
@@ -151,7 +151,8 @@ func (h *handlers) respondError(w http.ResponseWriter, status int, sentence stri
|
|||||||
|
|
||||||
// securityHeaders go on every response. The API returns JSON to
|
// securityHeaders go on every response. The API returns JSON to
|
||||||
// programs, so a browser may not frame, sniff, cache or refer from it,
|
// programs, so a browser may not frame, sniff, cache or refer from it,
|
||||||
// and must reach it over HTTPS.
|
// nor give it the camera, microphone or location, and must reach it
|
||||||
|
// over HTTPS.
|
||||||
func securityHeaders(next http.Handler) http.Handler {
|
func securityHeaders(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
header := w.Header()
|
header := w.Header()
|
||||||
@@ -160,6 +161,8 @@ func securityHeaders(next http.Handler) http.Handler {
|
|||||||
"default-src 'none'; frame-ancestors 'none'")
|
"default-src 'none'; frame-ancestors 'none'")
|
||||||
header.Set("X-Frame-Options", "DENY")
|
header.Set("X-Frame-Options", "DENY")
|
||||||
header.Set("Referrer-Policy", "no-referrer")
|
header.Set("Referrer-Policy", "no-referrer")
|
||||||
|
header.Set("Permissions-Policy",
|
||||||
|
"camera=(), microphone=(), geolocation=()")
|
||||||
header.Set("Strict-Transport-Security",
|
header.Set("Strict-Transport-Security",
|
||||||
"max-age=31536000; includeSubDomains")
|
"max-age=31536000; includeSubDomains")
|
||||||
header.Set("Cache-Control", "no-store")
|
header.Set("Cache-Control", "no-store")
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ func TestHeaders(t *testing.T) {
|
|||||||
"Content-Security-Policy": "default-src 'none'; frame-ancestors 'none'",
|
"Content-Security-Policy": "default-src 'none'; frame-ancestors 'none'",
|
||||||
"X-Frame-Options": "DENY",
|
"X-Frame-Options": "DENY",
|
||||||
"Referrer-Policy": "no-referrer",
|
"Referrer-Policy": "no-referrer",
|
||||||
|
"Permissions-Policy": "camera=(), microphone=(), geolocation=()",
|
||||||
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
|
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
|
||||||
"Cache-Control": "no-store",
|
"Cache-Control": "no-store",
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user