package contented import ( "encoding/json" "log" "net/http" "strings" "github.com/boltdb/bolt" "github.com/mxk/go-flowrate/flowrate" ) var SERVER_HEADER string = `contented/0.0.0-dev` type ServerPublicProperties struct { AppTitle string MaxUploadBytes int64 } type ServerOptions struct { DataDirectory string DBPath string BandwidthLimit int64 ServerPublicProperties } type Server struct { opts ServerOptions db *bolt.DB metadataBucket []byte } func NewServer(opts *ServerOptions) (*Server, error) { s := &Server{ opts: *opts, metadataBucket: []byte(`METADATA`), } b, err := bolt.Open(opts.DBPath, 0644, bolt.DefaultOptions) if err != nil { return nil, err } err = b.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucketIfNotExists(s.metadataBucket) return err }) if err != nil { return nil, err } s.db = b return s, nil } func (this *Server) serveJsonObject(w http.ResponseWriter, o interface{}) { jb, err := json.Marshal(o) if err != nil { log.Println(err.Error()) http.Error(w, "Internal error", 500) return } w.Header().Set(`Content-Type`, `application/json`) w.WriteHeader(200) w.Write(jb) } func (this *Server) handleAbout(w http.ResponseWriter) { this.serveJsonObject(w, this.opts.ServerPublicProperties) } func remoteIP(r *http.Request) string { return strings.TrimRight(strings.TrimRight(r.RemoteAddr, "0123456789"), ":") } const ( downloadUrlPrefix = `/get/` metadataUrlPrefix = `/info/` ) func (this *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set(`Server`, SERVER_HEADER) if this.opts.MaxUploadBytes > 0 { r.Body = http.MaxBytesReader(w, r.Body, this.opts.MaxUploadBytes) } if this.opts.BandwidthLimit > 0 { r.Body = flowrate.NewReader(r.Body, this.opts.BandwidthLimit) } // if r.Method == "GET" && strings.HasPrefix(r.URL.Path, downloadUrlPrefix) { this.handleView(w, r, r.URL.Path[len(downloadUrlPrefix):]) } else if r.Method == "GET" && strings.HasPrefix(r.URL.Path, metadataUrlPrefix) { this.handleInformation(w, r.URL.Path[len(metadataUrlPrefix):]) } else if r.Method == "GET" && r.URL.Path == `/about` { this.handleAbout(w) } else if r.Method == "POST" && r.URL.Path == `/upload` { this.handleUpload(w, r) } else { // TODO embed into binary http.FileServer(http.Dir(`static`)).ServeHTTP(w, r) } }