Static files are now served from memory. This feature's a little experimental, so it will need a lot of testing i.i
Added an executable file. Only works on Windows, if it doesn't work, then try building it for yourself with build.bat or go build Tweaked run.bat to make it more firewall friendly. It now generates an executable. Moved the files around to make it more organised. Added build.bat which you can use to build the program for you and install the libraries the software depends on.
This commit is contained in:
parent
dc77c43996
commit
689b1a804b
|
@ -1,2 +1,2 @@
|
||||||
src/uploads/*
|
uploads/*
|
||||||
bin/*
|
bin/*
|
|
@ -33,7 +33,7 @@ Set the password column of your user account in the database to what you want yo
|
||||||
|
|
||||||
# Run the program
|
# Run the program
|
||||||
|
|
||||||
go run errors.go main.go pages.go reply.go routes.go topic.go user.go utils.go forum.go group.go config.go
|
go run errors.go main.go pages.go reply.go routes.go topic.go user.go utils.go forum.go group.go files.go config.go
|
||||||
|
|
||||||
Alternatively, you could run the run.bat batch file on Windows.
|
Alternatively, you could run the run.bat batch file on Windows.
|
||||||
|
|
||||||
|
@ -64,5 +64,3 @@ Revamp the system for serving static files to make it much faster.
|
||||||
Tweak the CSS to make it responsive.
|
Tweak the CSS to make it responsive.
|
||||||
|
|
||||||
Add a forum cache.
|
Add a forum cache.
|
||||||
|
|
||||||
Cache the static files in memory.
|
|
||||||
|
|
|
@ -39,8 +39,7 @@ func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoginRequired(w http.ResponseWriter, r *http.Request, user User) {
|
func LoginRequired(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
errmsg := "You need to login to do that."
|
pi := Page{"Local Error","error",user,tList,"You need to login to do that."}
|
||||||
pi := Page{"Local Error","error",user,tList,errmsg}
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||||
|
@ -87,8 +86,7 @@ func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, is_js s
|
||||||
}
|
}
|
||||||
|
|
||||||
func Banned(w http.ResponseWriter, r *http.Request, user User) {
|
func Banned(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
errmsg := "You have been banned, thus you do not permission to do that."
|
pi := Page{"Banned","error",user,tList,"You have been banned from this site."}
|
||||||
pi := Page{"Local Error","error",user,tList,errmsg}
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||||
errpage := b.String()
|
errpage := b.String()
|
||||||
|
@ -97,30 +95,28 @@ func Banned(w http.ResponseWriter, r *http.Request, user User) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) {
|
func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) {
|
||||||
errmsg := "You have been banned from this site."
|
|
||||||
if is_js == "0" {
|
if is_js == "0" {
|
||||||
pi := Page{"Local Error","error",user,tList,errmsg}
|
pi := Page{"Banned","error",user,tList,"You have been banned from this site."}
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||||
errpage := b.String()
|
errpage := b.String()
|
||||||
w.WriteHeader(403)
|
w.WriteHeader(403)
|
||||||
fmt.Fprintln(w,errpage)
|
fmt.Fprintln(w,errpage)
|
||||||
} else {
|
} else {
|
||||||
http.Error(w,"{'errmsg': '" + errmsg + "'}",403)
|
http.Error(w,"{'errmsg': 'You have been banned from this site.'}",403)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) {
|
func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) {
|
||||||
errmsg := "You need to login to do that."
|
|
||||||
if is_js == "0" {
|
if is_js == "0" {
|
||||||
pi := Page{"Local Error","error",user,tList,errmsg}
|
pi := Page{"Local Error","error",user,tList,"You need to login to do that."}
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||||
errpage := b.String()
|
errpage := b.String()
|
||||||
w.WriteHeader(401)
|
w.WriteHeader(401)
|
||||||
fmt.Fprintln(w,errpage)
|
fmt.Fprintln(w,errpage)
|
||||||
} else {
|
} else {
|
||||||
http.Error(w,"{'errmsg': '" + errmsg + "'}",401)
|
http.Error(w,"{'errmsg': 'You need to login to do that.'}",401)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package main
|
||||||
|
import "io"
|
||||||
|
import "os"
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
type SFile struct
|
||||||
|
{
|
||||||
|
Data []byte
|
||||||
|
Pos int64
|
||||||
|
Length int64
|
||||||
|
Mimetype string
|
||||||
|
Info os.FileInfo
|
||||||
|
FormattedModTime string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r SFile) Read(b []byte) (n int, err error) {
|
||||||
|
n = 0
|
||||||
|
if r.Pos > r.Length {
|
||||||
|
return n, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
size := cap(b)
|
||||||
|
if size > 0 {
|
||||||
|
for n < size {
|
||||||
|
b[n] = r.Data[r.Pos]
|
||||||
|
n++
|
||||||
|
if r.Pos == r.Length {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
r.Pos++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r SFile) Seek(offset int64, whence int) (int64, error) {
|
||||||
|
if offset < 0 {
|
||||||
|
return 0, errors.New("negative position")
|
||||||
|
}
|
||||||
|
switch whence {
|
||||||
|
case 0:
|
||||||
|
r.Pos = offset
|
||||||
|
case 1:
|
||||||
|
r.Pos += offset
|
||||||
|
case 2:
|
||||||
|
r.Pos = r.Length + offset
|
||||||
|
default:
|
||||||
|
return 0, errors.New("invalid whence")
|
||||||
|
}
|
||||||
|
return r.Pos, nil
|
||||||
|
}
|
Binary file not shown.
|
@ -5,7 +5,9 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"log"
|
"log"
|
||||||
|
"mime"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"io/ioutil"
|
||||||
"html/template"
|
"html/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,6 +48,7 @@ var templates = template.Must(template.ParseGlob("templates/*"))
|
||||||
var no_css_tmpl = template.CSS("")
|
var no_css_tmpl = template.CSS("")
|
||||||
var staff_css_tmpl = template.CSS(staff_css)
|
var staff_css_tmpl = template.CSS(staff_css)
|
||||||
var groups map[int]Group = make(map[int]Group)
|
var groups map[int]Group = make(map[int]Group)
|
||||||
|
var static_files map[string]SFile = make(map[string]SFile)
|
||||||
|
|
||||||
func init_database(err error) {
|
func init_database(err error) {
|
||||||
if(dbpassword != ""){
|
if(dbpassword != ""){
|
||||||
|
@ -216,9 +219,30 @@ func main(){
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Loading the static files.")
|
||||||
|
files, err := ioutil.ReadDir("./public")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range files {
|
||||||
|
if f.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadFile("./public/" + f.Name())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("Added the '" + f.Name() + "' static file.")
|
||||||
|
static_files["/static/" + f.Name()] = SFile{data,0,int64(len(data)),mime.TypeByExtension(filepath.Ext(f.Name())),f,f.ModTime().UTC().Format(http.TimeFormat)}
|
||||||
|
}
|
||||||
|
|
||||||
// In a directory to stop it clashing with the other paths
|
// In a directory to stop it clashing with the other paths
|
||||||
fs_p := http.FileServer(http.Dir("./public"))
|
http.HandleFunc("/static/", route_static)
|
||||||
http.Handle("/static/", http.StripPrefix("/static/",fs_p))
|
//http.HandleFunc("/static/", route_fstatic)
|
||||||
|
//fs_p := http.FileServer(http.Dir("./public"))
|
||||||
|
//http.Handle("/static/", http.StripPrefix("/static/",fs_p))
|
||||||
fs_u := http.FileServer(http.Dir("./uploads"))
|
fs_u := http.FileServer(http.Dir("./uploads"))
|
||||||
http.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u))
|
http.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u))
|
||||||
|
|
|
@ -14,6 +14,13 @@ type Page struct
|
||||||
Something interface{}
|
Something interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PageSimple struct
|
||||||
|
{
|
||||||
|
Title string
|
||||||
|
Name string
|
||||||
|
Something interface{}
|
||||||
|
}
|
||||||
|
|
||||||
func add_custom_page(path string, f os.FileInfo, err error) error {
|
func add_custom_page(path string, f os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
Before Width: | Height: | Size: 539 B After Width: | Height: | Size: 539 B |
|
@ -6,6 +6,7 @@ import "strconv"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
import "regexp"
|
import "regexp"
|
||||||
import "strings"
|
import "strings"
|
||||||
|
import "time"
|
||||||
import "io"
|
import "io"
|
||||||
import "os"
|
import "os"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
@ -19,6 +20,26 @@ import "golang.org/x/crypto/bcrypt"
|
||||||
var tList map[int]interface{}
|
var tList map[int]interface{}
|
||||||
|
|
||||||
// GET functions
|
// GET functions
|
||||||
|
func route_static(w http.ResponseWriter, r *http.Request){
|
||||||
|
//name := r.URL.Path[len("/static/"):]
|
||||||
|
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && static_files[r.URL.Path].Info.ModTime().Before(t.Add(1*time.Second)) {
|
||||||
|
w.WriteHeader(http.StatusNotModified)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h := w.Header()
|
||||||
|
h.Set("Last-Modified", static_files[r.URL.Path].FormattedModTime)
|
||||||
|
h.Set("Content-Type", static_files[r.URL.Path].Mimetype)
|
||||||
|
h.Set("Content-Length", strconv.FormatInt(static_files[r.URL.Path].Length, 10))
|
||||||
|
//http.ServeContent(w,r,r.URL.Path,static_files[r.URL.Path].Info.ModTime(),static_files[r.URL.Path])
|
||||||
|
//w.Write(static_files[r.URL.Path].Data)
|
||||||
|
io.Copy(w, bytes.NewReader(static_files[r.URL.Path].Data))
|
||||||
|
//io.CopyN(w, bytes.NewReader(static_files[r.URL.Path].Data), static_files[r.URL.Path].Length)
|
||||||
|
}
|
||||||
|
|
||||||
|
func route_fstatic(w http.ResponseWriter, r *http.Request){
|
||||||
|
http.ServeFile(w, r, r.URL.Path)
|
||||||
|
}
|
||||||
|
|
||||||
func route_overview(w http.ResponseWriter, r *http.Request){
|
func route_overview(w http.ResponseWriter, r *http.Request){
|
||||||
user := SessionCheck(w,r)
|
user := SessionCheck(w,r)
|
||||||
pi := Page{"Overview","overview",user,tList,0}
|
pi := Page{"Overview","overview",user,tList,0}
|
||||||
|
@ -1206,8 +1227,7 @@ func route_panel_forums(w http.ResponseWriter, r *http.Request){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var forumList map[int]interface{}
|
var forumList map[int]interface{} = make(map[int]interface{})
|
||||||
forumList = make(map[int]interface{})
|
|
||||||
currentID := 0
|
currentID := 0
|
||||||
|
|
||||||
rows, err := db.Query("select fid, name from forums")
|
rows, err := db.Query("select fid, name from forums")
|
|
@ -1,2 +0,0 @@
|
||||||
go run errors.go main.go pages.go reply.go routes.go topic.go user.go utils.go config.go forum.go group.go
|
|
||||||
pause
|
|
Loading…
Reference in New Issue