Skip to content

Commit bb87bce

Browse files
committed
add HTTP headers: X-Frame-Options, Referrer-Policy
1 parent c0671ca commit bb87bce

File tree

4 files changed

+53
-17
lines changed

4 files changed

+53
-17
lines changed

server/hdl_websock.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
"github.com/gorilla/websocket"
1818
"github.com/tinode/chat/server/logs"
19+
"github.com/tinode/chat/server/store/types"
1920
)
2021

2122
const (
@@ -165,7 +166,7 @@ var upgrader = websocket.Upgrader{
165166
}
166167

167168
func serveWebSocket(wrt http.ResponseWriter, req *http.Request) {
168-
now := time.Now().UTC().Round(time.Millisecond)
169+
now := types.TimeNow()
169170

170171
if isValid, _ := checkAPIKey(getAPIKey(req)); !isValid {
171172
wrt.WriteHeader(http.StatusForbidden)

server/http.go

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,17 +169,6 @@ func signalHandler() <-chan bool {
169169
return stop
170170
}
171171

172-
// Wrapper for http.Handler which optionally adds a Strict-Transport-Security to the response.
173-
func hstsHandler(handler http.Handler) http.Handler {
174-
if globals.tlsStrictMaxAge != "" {
175-
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
176-
w.Header().Set("Strict-Transport-Security", "max-age="+globals.tlsStrictMaxAge)
177-
handler.ServeHTTP(w, r)
178-
})
179-
}
180-
return handler
181-
}
182-
183172
// The following code is used to intercept HTTP errors so they can be wrapped into json.
184173

185174
// Wrapper around http.ResponseWriter which detects status set to 400+ and replaces
@@ -270,6 +259,32 @@ func tlsRedirect(toPort string) http.HandlerFunc {
270259
}
271260
}
272261

262+
// Wrapper for adding optional HTTP headers:
263+
// - Strict-Transport-Security
264+
// - X-Frame-Options
265+
// - Referrer-Policy
266+
func optionalHttpHeaders(handler http.Handler) http.Handler {
267+
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
268+
w.Header().Set("Referrer-Policy", "origin")
269+
handler.ServeHTTP(w, r)
270+
})
271+
272+
if globals.tlsStrictMaxAge != "" {
273+
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
274+
w.Header().Set("Strict-Transport-Security", "max-age="+globals.tlsStrictMaxAge)
275+
handler.ServeHTTP(w, r)
276+
})
277+
}
278+
279+
if globals.xFrameOptions != "-" {
280+
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
281+
w.Header().Set("X-Frame-Options", globals.xFrameOptions)
282+
handler.ServeHTTP(w, r)
283+
})
284+
}
285+
return handler
286+
}
287+
273288
// Wrapper for http.Handler which optionally adds a Cache-Control header to the response
274289
func cacheControlHandler(maxAge int, handler http.Handler) http.Handler {
275290
if maxAge > 0 {

server/main.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ var globals struct {
188188
// Prioritize X-Forwarded-For header as the source of IP address of the client.
189189
useXForwardedFor bool
190190

191+
// Add X-Frame-Options header to HTTP response.
192+
xFrameOptions string
193+
191194
// Country code to assign to sessions by default.
192195
defaultCountryCode string
193196

@@ -286,6 +289,9 @@ type configType struct {
286289
// Take IP address of the client from HTTP header 'X-Forwarded-For'.
287290
// Useful when tinode is behind a proxy. If missing, fallback to default RemoteAddr.
288291
UseXForwardedFor bool `json:"use_x_forwarded_for"`
292+
// Add X-Frame-Options to HTTP response headers. It should be one of "DENY", "SAMEORIGIN",
293+
// "-" (disabled). The default is SAMEORIGIN.
294+
XFrameOptions string `json:"x_frame_options"`
289295
// 2-letter country code (ISO 3166-1 alpha-2) to assign to sessions by default
290296
// when the country isn't specified by the client explicitly and
291297
// it's impossible to infer it.
@@ -556,6 +562,16 @@ func main() {
556562
globals.defaultCountryCode = defaultCountryCode
557563
}
558564

565+
// Configuration of X-Frame-Options header.
566+
globals.xFrameOptions = config.XFrameOptions
567+
if globals.xFrameOptions == "" {
568+
globals.xFrameOptions = "SAMEORIGIN"
569+
}
570+
if globals.xFrameOptions != "SAMEORIGIN" && globals.xFrameOptions != "DENY" && globals.xFrameOptions != "-" {
571+
logs.Warn.Println("Ignored invalid x_frame_options", config.XFrameOptions)
572+
globals.xFrameOptions = "SAMEORIGIN"
573+
}
574+
559575
// Websocket compression.
560576
globals.wsCompression = !config.WSCompressionDisabled
561577

@@ -666,15 +682,15 @@ func main() {
666682
}
667683
}
668684
mux.Handle(staticMountPoint,
669-
// Add optional Cache-Control header
685+
// Add optional Cache-Control header.
670686
cacheControlHandler(config.CacheControl,
671-
// Optionally add Strict-Transport_security to the response
672-
hstsHandler(
673-
// Add gzip compression
687+
// Optionally add Strict-Transport-Security and X-Frame-Options to the response.
688+
optionalHttpHeaders(
689+
// Add gzip compression.
674690
gh.CompressHandler(
675691
// And add custom formatter of errors.
676692
httpErrorHandler(
677-
// Remove mount point prefix
693+
// Remove mount point prefix.
678694
http.StripPrefix(staticMountPoint,
679695
http.FileServer(http.Dir(*staticPath))))))))
680696
logs.Info.Printf("Serving static content from '%s' at '%s'", *staticPath, staticMountPoint)

server/tinode.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363
// Useful when Tinode is behind a proxy. If missing, fallback to default RemoteAddr.
6464
"use_x_forwarded_for": true,
6565

66+
// Add X-Frame-Options to HTTP response headers. It should be one of "DENY", "SAMEORIGIN",
67+
// "-" (disabled). If the option is missing then it's treated as SAMEORIGIN.
68+
"x_frame_options": "SAMEORIGIN",
69+
6670
// 2-letter country code to assign to sessions by default when the country isn't specified
6771
// by the client explicitly and it's impossible to infer it.
6872
// If missing, the server will default to "US".

0 commit comments

Comments
 (0)