Upped the compression level for static files.

Experimenting with compressing everything.
Fixed the live things.

Playing around with topic buttons in Nox.
This commit is contained in:
Azareal 2018-08-21 18:00:35 +10:00
parent 2e0f2bc7b6
commit 7b8943517b
8 changed files with 119 additions and 23 deletions

View File

@ -216,7 +216,10 @@ func (list SFileList) JSTmplInit() error {
path = tmplName + ".js" path = tmplName + ".js"
DebugLog("js path: ", path) DebugLog("js path: ", path)
var ext = filepath.Ext("/tmpl_client/" + path) var ext = filepath.Ext("/tmpl_client/" + path)
gzipData := compressBytesGzip(data) gzipData, err := compressBytesGzip(data)
if err != nil {
return err
}
list.Set("/static/"+path, SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}) list.Set("/static/"+path, SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
@ -239,7 +242,10 @@ func (list SFileList) Init() error {
path = strings.TrimPrefix(path, "public/") path = strings.TrimPrefix(path, "public/")
var ext = filepath.Ext("/public/" + path) var ext = filepath.Ext("/public/" + path)
gzipData := compressBytesGzip(data) gzipData, err := compressBytesGzip(data)
if err != nil {
return err
}
list.Set("/static/"+path, SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}) list.Set("/static/"+path, SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
@ -264,7 +270,10 @@ func (list SFileList) Add(path string, prefix string) error {
var ext = filepath.Ext(path) var ext = filepath.Ext(path)
path = strings.TrimPrefix(path, prefix) path = strings.TrimPrefix(path, prefix)
gzipData := compressBytesGzip(data) gzipData, err := compressBytesGzip(data)
if err != nil {
return err
}
list.Set("/static"+path, SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}) list.Set("/static"+path, SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
@ -285,10 +294,19 @@ func (list SFileList) Set(name string, data SFile) {
list[name] = data list[name] = data
} }
func compressBytesGzip(in []byte) []byte { func compressBytesGzip(in []byte) ([]byte, error) {
var buff bytes.Buffer var buff bytes.Buffer
gz := gzip.NewWriter(&buff) gz, err := gzip.NewWriterLevel(&buff, gzip.BestCompression)
_, _ = gz.Write(in) // TODO: What if this errors? What circumstances could it error under? Should we add a second return value? if err != nil {
_ = gz.Close() return nil, err
return buff.Bytes() }
_, err = gz.Write(in)
if err != nil {
return nil, err
}
err = gz.Close()
if err != nil {
return nil, err
}
return buff.Bytes(), nil
} }

View File

@ -110,7 +110,11 @@ func (theme *Theme) AddThemeStaticFiles() error {
} }
path = strings.TrimPrefix(path, "themes/"+theme.Name+"/public") path = strings.TrimPrefix(path, "themes/"+theme.Name+"/public")
gzipData := compressBytesGzip(data) gzipData, err := compressBytesGzip(data)
if err != nil {
return err
}
StaticFiles.Set("/static/"+theme.Name+path, SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}) StaticFiles.Set("/static/"+theme.Name+path, SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
DebugLog("Added the '/" + theme.Name + path + "' static file for theme " + theme.Name + ".") DebugLog("Added the '/" + theme.Name + path + "' static file for theme " + theme.Name + ".")

View File

@ -6,9 +6,11 @@ import (
"log" "log"
"strings" "strings"
"strconv" "strconv"
"compress/gzip"
"sync" "sync"
"sync/atomic" "sync/atomic"
"errors" "errors"
"io"
"os" "os"
"net/http" "net/http"
@ -528,6 +530,15 @@ func init() {
counters.SetReverseOSMapEnum(reverseOSMapEnum) counters.SetReverseOSMapEnum(reverseOSMapEnum)
} }
type gzipResponseWriter struct {
io.Writer
http.ResponseWriter
}
func (w gzipResponseWriter) Write(b []byte) (int, error) {
return w.Writer.Write(b)
}
type WriterIntercept struct { type WriterIntercept struct {
w http.ResponseWriter w http.ResponseWriter
code int code int
@ -668,12 +679,6 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
h := w.Header()
h.Set("X-Frame-Options", "deny")
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
// TODO: Set the content policy header
h.Set("X-Content-Type-Options", "nosniff")
// TODO: Cover more suspicious strings and at a lower layer than this // TODO: Cover more suspicious strings and at a lower layer than this
for _, char := range req.URL.Path { for _, char := range req.URL.Path {
if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) { if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) {
@ -699,6 +704,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1] req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
} }
if prefix != "/ws" {
h := w.Header()
h.Set("X-Frame-Options", "deny")
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
// TODO: Set the content policy header
h.Set("X-Content-Type-Options", "nosniff")
}
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
router.DumpRequest(req,"before routes.StaticFile") router.DumpRequest(req,"before routes.StaticFile")
} }
@ -874,6 +887,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
"routeMapEnum: ", routeMapEnum) "routeMapEnum: ", routeMapEnum)
} }
// Disable Gzip when SSL is disabled for security reasons?
if prefix != "/ws" && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
w.Header().Set("Content-Encoding", "gzip")
w.Header().Set("Content-Type", "text/html")
gz := gzip.NewWriter(w)
defer gz.Close()
w = gzipResponseWriter{Writer: gz, ResponseWriter: w}
}
router.routeSwitch(w, req, user, prefix, extraData) router.routeSwitch(w, req, user, prefix, extraData)
} }
@ -2035,6 +2056,7 @@ func (router *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, u
common.NotFound(w,req,nil) common.NotFound(w,req,nil)
return return
} }
w.Header().Del("Content-Type")
counters.RouteViewCounter.Bump(121) counters.RouteViewCounter.Bump(121)
req.URL.Path += extraData req.URL.Path += extraData
// TODO: Find a way to propagate errors up from this? // TODO: Find a way to propagate errors up from this?

View File

@ -224,9 +224,11 @@ import (
"log" "log"
"strings" "strings"
"strconv" "strconv"
"compress/gzip"
"sync" "sync"
"sync/atomic" "sync/atomic"
"errors" "errors"
"io"
"os" "os"
"net/http" "net/http"
@ -305,6 +307,15 @@ func init() {
counters.SetReverseOSMapEnum(reverseOSMapEnum) counters.SetReverseOSMapEnum(reverseOSMapEnum)
} }
type gzipResponseWriter struct {
io.Writer
http.ResponseWriter
}
func (w gzipResponseWriter) Write(b []byte) (int, error) {
return w.Writer.Write(b)
}
type WriterIntercept struct { type WriterIntercept struct {
w http.ResponseWriter w http.ResponseWriter
code int code int
@ -445,12 +456,6 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
h := w.Header()
h.Set("X-Frame-Options", "deny")
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
// TODO: Set the content policy header
h.Set("X-Content-Type-Options", "nosniff")
// TODO: Cover more suspicious strings and at a lower layer than this // TODO: Cover more suspicious strings and at a lower layer than this
for _, char := range req.URL.Path { for _, char := range req.URL.Path {
if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) { if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) {
@ -476,6 +481,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1] req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
} }
if prefix != "/ws" {
h := w.Header()
h.Set("X-Frame-Options", "deny")
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
// TODO: Set the content policy header
h.Set("X-Content-Type-Options", "nosniff")
}
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
router.DumpRequest(req,"before routes.StaticFile") router.DumpRequest(req,"before routes.StaticFile")
} }
@ -651,6 +664,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
"routeMapEnum: ", routeMapEnum) "routeMapEnum: ", routeMapEnum)
} }
// Disable Gzip when SSL is disabled for security reasons?
if prefix != "/ws" && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
w.Header().Set("Content-Encoding", "gzip")
w.Header().Set("Content-Type", "text/html")
gz := gzip.NewWriter(w)
defer gz.Close()
w = gzipResponseWriter{Writer: gz, ResponseWriter: w}
}
router.routeSwitch(w, req, user, prefix, extraData) router.routeSwitch(w, req, user, prefix, extraData)
} }
@ -668,6 +689,7 @@ func (router *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, u
common.NotFound(w,req,nil) common.NotFound(w,req,nil)
return return
} }
w.Header().Del("Content-Type")
counters.RouteViewCounter.Bump({{index .AllRouteMap "routes.UploadedFile" }}) counters.RouteViewCounter.Bump({{index .AllRouteMap "routes.UploadedFile" }})
req.URL.Path += extraData req.URL.Path += extraData
// TODO: Find a way to propagate errors up from this? // TODO: Find a way to propagate errors up from this?

View File

@ -72,6 +72,7 @@
<div class="hide_on_edit topic_content user_content" itemprop="text">{{.Topic.ContentHTML}}</div> <div class="hide_on_edit topic_content user_content" itemprop="text">{{.Topic.ContentHTML}}</div>
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea> <textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea>
<div class="controls button_container{{if .Topic.LikeCount}} has_likes{{end}}"> <div class="controls button_container{{if .Topic.LikeCount}} has_likes{{end}}">
<div class="action_button_left">
{{if .CurrentUser.Loggedin}} {{if .CurrentUser.Loggedin}}
{{if .CurrentUser.Perms.LikeItem}}<a href="/topic/like/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}" class="action_button like_item {{if .Topic.Liked}}remove_like{{else}}add_like{{end}}" aria-label="{{lang "topic.like_aria"}}" data-action="like"></a>{{end}} {{if .CurrentUser.Perms.LikeItem}}<a href="/topic/like/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}" class="action_button like_item {{if .Topic.Liked}}remove_like{{else}}add_like{{end}}" aria-label="{{lang "topic.like_aria"}}" data-action="like"></a>{{end}}
{{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}} {{if not .Topic.IsClosed or .CurrentUser.Perms.CloseTopic}}
@ -86,6 +87,7 @@
<a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="action_button report_item" aria-label="{{lang "topic.report_aria"}}" data-action="report"></a> <a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="action_button report_item" aria-label="{{lang "topic.report_aria"}}" data-action="report"></a>
<a href="#" class="action_button button_menu"></a> <a href="#" class="action_button button_menu"></a>
{{end}} {{end}}
</div>
<div class="action_button_right"> <div class="action_button_right">
<a class="action_button like_count hide_on_micro" aria-label="{{lang "topic.like_count_aria"}}">{{.Topic.LikeCount}}</a> <a class="action_button like_count hide_on_micro" aria-label="{{lang "topic.like_count_aria"}}">{{.Topic.LikeCount}}</a>
<a class="action_button created_at hide_on_mobile">{{.Topic.RelativeCreatedAt}}</a> <a class="action_button created_at hide_on_mobile">{{.Topic.RelativeCreatedAt}}</a>

View File

@ -14,6 +14,7 @@
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}} {{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div> <div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
<div class="controls button_container{{if .LikeCount}} has_likes{{end}}"> <div class="controls button_container{{if .LikeCount}} has_likes{{end}}">
<div class="action_button_left">
{{if $.CurrentUser.Loggedin}} {{if $.CurrentUser.Loggedin}}
{{if $.CurrentUser.Perms.LikeItem}}<a href="/reply/like/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="action_button like_item {{if .Liked}}remove_like{{else}}add_like{{end}}" aria-label="{{lang "topic.post_like_aria"}}" data-action="like"></a>{{end}} {{if $.CurrentUser.Perms.LikeItem}}<a href="/reply/like/submit/{{.ID}}?session={{$.CurrentUser.Session}}" class="action_button like_item {{if .Liked}}remove_like{{else}}add_like{{end}}" aria-label="{{lang "topic.post_like_aria"}}" data-action="like"></a>{{end}}
{{if not $.Topic.IsClosed or $.CurrentUser.Perms.CloseTopic}} {{if not $.Topic.IsClosed or $.CurrentUser.Perms.CloseTopic}}
@ -24,6 +25,7 @@
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button report_item" aria-label="{{lang "topic.report_aria"}}" data-action="report"></a> <a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button report_item" aria-label="{{lang "topic.report_aria"}}" data-action="report"></a>
<a href="#" class="action_button button_menu"></a> <a href="#" class="action_button button_menu"></a>
{{end}} {{end}}
</div>
<div class="action_button_right"> <div class="action_button_right">
<a class="action_button like_count hide_on_micro" aria-label="{{lang "topic.post_like_count_tooltip"}}">{{.LikeCount}}</a> <a class="action_button like_count hide_on_micro" aria-label="{{lang "topic.post_like_count_tooltip"}}">{{.LikeCount}}</a>
<a class="action_button created_at hide_on_mobile">{{.RelativeCreatedAt}}</a> <a class="action_button created_at hide_on_mobile">{{.RelativeCreatedAt}}</a>

View File

@ -1022,6 +1022,9 @@ textarea {
font-size: 14px; font-size: 14px;
display: inline-block; display: inline-block;
} }
.action_button_left {
display: flex;
}
.action_button_right { .action_button_right {
display: inline-flex; display: inline-flex;
margin-left: auto; margin-left: auto;

View File

@ -586,6 +586,9 @@ button, .formbutton, .panel_right_button {
font-size: 15px; font-size: 15px;
color: #dddddd; color: #dddddd;
} }
.post_item .action_button_left {
display: flex;
}
.post_item .action_button_right { .post_item .action_button_right {
margin-left: auto; margin-left: auto;
display: flex; display: flex;
@ -657,6 +660,26 @@ button, .formbutton, .panel_right_button {
display: none; display: none;
} }
.post_item .content_container {
background-color: transparent;
padding: 0px;
}
.post_item .user_content {
background-color: #444444;
padding: 16px;
}
.post_item .button_container {
display: block;
margin-top: 8px;
}
.post_item .action_button_left {
display: block;
background-color: #444444;
padding: 10px;
}
.ip_item.hide_on_mobile {
display: none;
}
.post_item, .topic_reply_container { .post_item, .topic_reply_container {
flex-direction: column; flex-direction: column;
} }