save allocs in router

better logging for bad char in path
router_pre_route hook now returns properly
This commit is contained in:
Azareal 2020-03-27 16:05:35 +10:00
parent dd5aef22dd
commit 3adee57b37
4 changed files with 43 additions and 25 deletions

View File

@ -33,13 +33,13 @@ func minifyCSS(data string) string {
// TODO: Convert this to three character hex strings whenever possible? // TODO: Convert this to three character hex strings whenever possible?
// TODO: Write unit tests for this // TODO: Write unit tests for this
// nolint // nolint
func rgbToHexstr(red int, green int, blue int) string { func rgbToHexstr(red, green, blue int) string {
return strconv.FormatInt(int64(red), 16) + strconv.FormatInt(int64(green), 16) + strconv.FormatInt(int64(blue), 16) return strconv.FormatInt(int64(red), 16) + strconv.FormatInt(int64(green), 16) + strconv.FormatInt(int64(blue), 16)
} }
/* /*
// TODO: Write unit tests for this // TODO: Write unit tests for this
func hexstrToRgb(hexstr string) (red int, blue int, green int, err error) { func hexstrToRgb(hexstr string) (red, blue, green int, err error) {
// Strip the # at the start // Strip the # at the start
if hexstr[0] == '#' { if hexstr[0] == '#' {
hexstr = strings.TrimPrefix(hexstr,"#") hexstr = strings.TrimPrefix(hexstr,"#")

View File

@ -30,11 +30,11 @@ type TopicStore interface {
BulkGetMap(ids []int) (list map[int]*Topic, err error) BulkGetMap(ids []int) (list map[int]*Topic, err error)
Exists(id int) bool Exists(id int) bool
Create(fid int, name, content string, uid int, ip string) (tid int, err error) Create(fid int, name, content string, uid int, ip string) (tid int, err error)
AddLastTopic(item *Topic, fid int) error // unimplemented AddLastTopic(t *Topic, fid int) error // unimplemented
Reload(id int) error // Too much SQL logic to move into TopicCache Reload(id int) error // Too much SQL logic to move into TopicCache
// TODO: Implement these two methods // TODO: Implement these two methods
//Replies(tid int) ([]*Reply, error) //Replies(tid int) ([]*Reply, error)
//RepliesRange(tid int, lower int, higher int) ([]*Reply, error) //RepliesRange(tid, lower, higher int) ([]*Reply, error)
Count() int Count() int
CountUser(uid int) int CountUser(uid int) int
CountMegaUser(uid int) int CountMegaUser(uid int) int

View File

@ -948,16 +948,18 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
shost = strings.TrimPrefix(spl[0],"[") shost = strings.TrimPrefix(spl[0],"[")
sport = strings.TrimPrefix(spl[1],":") sport = strings.TrimPrefix(spl[1],":")
} else { } else if strings.Contains(req.Host,":") {
spl := strings.Split(req.Host,":") spl := strings.Split(req.Host,":")
if len(spl) > 2 { if len(spl) > 2 {
malformedRequest(1) malformedRequest(1)
return return
} }
shost = spl[0] shost = spl[0]
if len(spl)==2 { //if len(spl)==2 {
sport = spl[1] sport = spl[1]
} //}
} else {
shost = req.Host
} }
// TODO: Reject requests from non-local IPs, if the site host is set to localhost or a localhost IP // TODO: Reject requests from non-local IPs, if the site host is set to localhost or a localhost IP
if !c.Config.LoosePort && c.Site.PortInt != 80 && c.Site.PortInt != 443 && sport != c.Site.Port { if !c.Config.LoosePort && c.Site.PortInt != 80 && c.Site.PortInt != 443 && sport != c.Site.Port {
@ -999,12 +1001,13 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// 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 _, ch := range req.URL.Path { //char for _, ch := range req.URL.Path { //char
if ch != '&' && !(ch > 44 && ch < 58) && ch != '=' && ch != '?' && !(ch > 64 && ch < 91) && ch != '\\' && ch != '_' && !(ch > 96 && ch < 123) { if ch != '&' && !(ch > 44 && ch < 58) && ch != '=' && ch != '?' && !(ch > 64 && ch < 91) && ch != '\\' && ch != '_' && !(ch > 96 && ch < 123) {
r.SuspiciousRequest(req,"Bad char in path") r.SuspiciousRequest(req,"Bad char '"+string(ch)+"' in path")
break break
} }
} }
lp := strings.ToLower(req.URL.Path) lp := strings.ToLower(req.URL.Path)
// TODO: Flag any requests which has a dot with anything but a number after that // TODO: Flag any requests which has a dot with anything but a number after that
// TODO: Use HasSuffix to avoid over-scanning?
if strings.Contains(lp,"..")/* || strings.Contains(lp,"--")*/ || strings.Contains(lp,".php") || strings.Contains(lp,".asp") || strings.Contains(lp,".cgi") || strings.Contains(lp,".py") || strings.Contains(lp,".sql") || strings.Contains(lp,".action") { if strings.Contains(lp,"..")/* || strings.Contains(lp,"--")*/ || strings.Contains(lp,".php") || strings.Contains(lp,".asp") || strings.Contains(lp,".cgi") || strings.Contains(lp,".py") || strings.Contains(lp,".sql") || strings.Contains(lp,".action") {
r.SuspiciousRequest(req,"Bad snippet in path") r.SuspiciousRequest(req,"Bad snippet in path")
} }
@ -1050,6 +1053,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
routes.StaticFile(w, req) routes.StaticFile(w, req)
return return
} }
// TODO: Handle JS routes
if atomic.LoadInt32(&c.IsDBDown) == 1 { if atomic.LoadInt32(&c.IsDBDown) == 1 {
c.DatabaseError(w, req) c.DatabaseError(w, req)
return return
@ -1065,7 +1069,6 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like. // Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like.
// TODO: Add a setting to disable this? // TODO: Add a setting to disable this?
// TODO: Use a more efficient detector instead of smashing every possible combination in // TODO: Use a more efficient detector instead of smashing every possible combination in
//var agent string
var agent int var agent int
if !c.Config.DisableAnalytics { if !c.Config.DisableAnalytics {
@ -1086,6 +1089,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
var os int var os int
for _, it := range uutils.StringToBytes(ua) { for _, it := range uutils.StringToBytes(ua) {
if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' { if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' {
// TODO: Store an index and slice that instead?
buffer = append(buffer, it) buffer = append(buffer, it)
} else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' /*|| (it == ':' && bytes.Equal(buffer,[]byte("http")))*/ || it == ',' || it == '/' { } else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' /*|| (it == ':' && bytes.Equal(buffer,[]byte("http")))*/ || it == ',' || it == '/' {
if len(buffer) != 0 { if len(buffer) != 0 {
@ -1178,6 +1182,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// TODO: Default to anything other than en, if anything else is present, to avoid over-representing it for multi-linguals? // TODO: Default to anything other than en, if anything else is present, to avoid over-representing it for multi-linguals?
lang := req.Header.Get("Accept-Language") lang := req.Header.Get("Accept-Language")
if lang != "" { if lang != "" {
// TODO: Reduce allocs here
lLang := strings.Split(strings.TrimSpace(lang),"-") lLang := strings.Split(strings.TrimSpace(lang),"-")
tLang := strings.Split(strings.Split(lLang[0],";")[0],",") tLang := strings.Split(strings.Split(lLang[0],";")[0],",")
c.DebugDetail("tLang:", tLang) c.DebugDetail("tLang:", tLang)
@ -1225,6 +1230,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
"after PreRoute\n" + "after PreRoute\n" +
"routeMapEnum: ", routeMapEnum) "routeMapEnum: ", routeMapEnum)
} }
//log.Println("req: ", req)
// Disable Gzip when SSL is disabled for security reasons? // Disable Gzip when SSL is disabled for security reasons?
if prefix != "/ws" && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { if prefix != "/ws" && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
@ -1232,26 +1238,29 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
h.Set("Content-Encoding", "gzip") h.Set("Content-Encoding", "gzip")
gzw := c.GzipResponseWriter{Writer: gzip.NewWriter(w), ResponseWriter: w} gzw := c.GzipResponseWriter{Writer: gzip.NewWriter(w), ResponseWriter: w}
defer func() { defer func() {
//h := w.Header()
if h.Get("Content-Encoding") == "gzip" && h.Get("X-I") == "" { if h.Get("Content-Encoding") == "gzip" && h.Get("X-I") == "" {
//log.Print("push gzip close")
gzw.Writer.(*gzip.Writer).Close() gzw.Writer.(*gzip.Writer).Close()
} }
}() }()
w = gzw w = gzw
} }
skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix)
if skip || ferr != nil {
r.handleError(ferr,w,req,user)
return
}
var extraData string var extraData string
if req.URL.Path[len(req.URL.Path) - 1] != '/' { if req.URL.Path[len(req.URL.Path) - 1] != '/' {
extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:] extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:]
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1] req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
} }
skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData)
if skip || ferr != nil {
r.handleError(ferr,w,req,user)
}
ferr = r.routeSwitch(w, req, user, prefix, extraData) ferr = r.routeSwitch(w, req, user, prefix, extraData)
if ferr != nil { if ferr != nil {
r.handleError(ferr,w,req,user) r.handleError(ferr,w,req,user)
return
} }
/*if !c.Config.DisableAnalytics { /*if !c.Config.DisableAnalytics {
co.RouteViewCounter.Bump(id) co.RouteViewCounter.Bump(id)

View File

@ -626,16 +626,18 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
shost = strings.TrimPrefix(spl[0],"[") shost = strings.TrimPrefix(spl[0],"[")
sport = strings.TrimPrefix(spl[1],":") sport = strings.TrimPrefix(spl[1],":")
} else { } else if strings.Contains(req.Host,":") {
spl := strings.Split(req.Host,":") spl := strings.Split(req.Host,":")
if len(spl) > 2 { if len(spl) > 2 {
malformedRequest(1) malformedRequest(1)
return return
} }
shost = spl[0] shost = spl[0]
if len(spl)==2 { //if len(spl)==2 {
sport = spl[1] sport = spl[1]
} //}
} else {
shost = req.Host
} }
// TODO: Reject requests from non-local IPs, if the site host is set to localhost or a localhost IP // TODO: Reject requests from non-local IPs, if the site host is set to localhost or a localhost IP
if !c.Config.LoosePort && c.Site.PortInt != 80 && c.Site.PortInt != 443 && sport != c.Site.Port { if !c.Config.LoosePort && c.Site.PortInt != 80 && c.Site.PortInt != 443 && sport != c.Site.Port {
@ -677,12 +679,13 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// 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 _, ch := range req.URL.Path { //char for _, ch := range req.URL.Path { //char
if ch != '&' && !(ch > 44 && ch < 58) && ch != '=' && ch != '?' && !(ch > 64 && ch < 91) && ch != '\\' && ch != '_' && !(ch > 96 && ch < 123) { if ch != '&' && !(ch > 44 && ch < 58) && ch != '=' && ch != '?' && !(ch > 64 && ch < 91) && ch != '\\' && ch != '_' && !(ch > 96 && ch < 123) {
r.SuspiciousRequest(req,"Bad char in path") r.SuspiciousRequest(req,"Bad char '"+string(ch)+"' in path")
break break
} }
} }
lp := strings.ToLower(req.URL.Path) lp := strings.ToLower(req.URL.Path)
// TODO: Flag any requests which has a dot with anything but a number after that // TODO: Flag any requests which has a dot with anything but a number after that
// TODO: Use HasSuffix to avoid over-scanning?
if strings.Contains(lp,"..")/* || strings.Contains(lp,"--")*/ || strings.Contains(lp,".php") || strings.Contains(lp,".asp") || strings.Contains(lp,".cgi") || strings.Contains(lp,".py") || strings.Contains(lp,".sql") || strings.Contains(lp,".action") { if strings.Contains(lp,"..")/* || strings.Contains(lp,"--")*/ || strings.Contains(lp,".php") || strings.Contains(lp,".asp") || strings.Contains(lp,".cgi") || strings.Contains(lp,".py") || strings.Contains(lp,".sql") || strings.Contains(lp,".action") {
r.SuspiciousRequest(req,"Bad snippet in path") r.SuspiciousRequest(req,"Bad snippet in path")
} }
@ -728,6 +731,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
routes.StaticFile(w, req) routes.StaticFile(w, req)
return return
} }
// TODO: Handle JS routes
if atomic.LoadInt32(&c.IsDBDown) == 1 { if atomic.LoadInt32(&c.IsDBDown) == 1 {
c.DatabaseError(w, req) c.DatabaseError(w, req)
return return
@ -743,7 +747,6 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like. // Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like.
// TODO: Add a setting to disable this? // TODO: Add a setting to disable this?
// TODO: Use a more efficient detector instead of smashing every possible combination in // TODO: Use a more efficient detector instead of smashing every possible combination in
//var agent string
var agent int var agent int
if !c.Config.DisableAnalytics { if !c.Config.DisableAnalytics {
@ -764,6 +767,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
var os int var os int
for _, it := range uutils.StringToBytes(ua) { for _, it := range uutils.StringToBytes(ua) {
if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' { if (it > 64 && it < 91) || (it > 96 && it < 123) || it == '_' {
// TODO: Store an index and slice that instead?
buffer = append(buffer, it) buffer = append(buffer, it)
} else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' /*|| (it == ':' && bytes.Equal(buffer,[]byte("http")))*/ || it == ',' || it == '/' { } else if it == ' ' || it == '(' || it == ')' || it == '-' || (it > 47 && it < 58) || it == ';' || it == ':' || it == '.' || it == '+' || it == '~' || it == '@' /*|| (it == ':' && bytes.Equal(buffer,[]byte("http")))*/ || it == ',' || it == '/' {
if len(buffer) != 0 { if len(buffer) != 0 {
@ -856,6 +860,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// TODO: Default to anything other than en, if anything else is present, to avoid over-representing it for multi-linguals? // TODO: Default to anything other than en, if anything else is present, to avoid over-representing it for multi-linguals?
lang := req.Header.Get("Accept-Language") lang := req.Header.Get("Accept-Language")
if lang != "" { if lang != "" {
// TODO: Reduce allocs here
lLang := strings.Split(strings.TrimSpace(lang),"-") lLang := strings.Split(strings.TrimSpace(lang),"-")
tLang := strings.Split(strings.Split(lLang[0],";")[0],",") tLang := strings.Split(strings.Split(lLang[0],";")[0],",")
c.DebugDetail("tLang:", tLang) c.DebugDetail("tLang:", tLang)
@ -903,6 +908,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
"after PreRoute\n" + "after PreRoute\n" +
"routeMapEnum: ", routeMapEnum) "routeMapEnum: ", routeMapEnum)
} }
//log.Println("req: ", req)
// Disable Gzip when SSL is disabled for security reasons? // Disable Gzip when SSL is disabled for security reasons?
if prefix != "/ws" && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { if prefix != "/ws" && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
@ -910,26 +916,29 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
h.Set("Content-Encoding", "gzip") h.Set("Content-Encoding", "gzip")
gzw := c.GzipResponseWriter{Writer: gzip.NewWriter(w), ResponseWriter: w} gzw := c.GzipResponseWriter{Writer: gzip.NewWriter(w), ResponseWriter: w}
defer func() { defer func() {
//h := w.Header()
if h.Get("Content-Encoding") == "gzip" && h.Get("X-I") == "" { if h.Get("Content-Encoding") == "gzip" && h.Get("X-I") == "" {
//log.Print("push gzip close")
gzw.Writer.(*gzip.Writer).Close() gzw.Writer.(*gzip.Writer).Close()
} }
}() }()
w = gzw w = gzw
} }
skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix)
if skip || ferr != nil {
r.handleError(ferr,w,req,user)
return
}
var extraData string var extraData string
if req.URL.Path[len(req.URL.Path) - 1] != '/' { if req.URL.Path[len(req.URL.Path) - 1] != '/' {
extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:] extraData = req.URL.Path[strings.LastIndexByte(req.URL.Path,'/') + 1:]
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1] req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
} }
skip, ferr = hTbl.VhookSkippable("router_pre_route", w, req, user, prefix, extraData)
if skip || ferr != nil {
r.handleError(ferr,w,req,user)
}
ferr = r.routeSwitch(w, req, user, prefix, extraData) ferr = r.routeSwitch(w, req, user, prefix, extraData)
if ferr != nil { if ferr != nil {
r.handleError(ferr,w,req,user) r.handleError(ferr,w,req,user)
return
} }
/*if !c.Config.DisableAnalytics { /*if !c.Config.DisableAnalytics {
co.RouteViewCounter.Bump(id) co.RouteViewCounter.Bump(id)