Skip to content

Instantly share code, notes, and snippets.

@veer66
Created November 4, 2013 10:28
Show Gist options
  • Save veer66/7300745 to your computer and use it in GitHub Desktop.
Save veer66/7300745 to your computer and use it in GitHub Desktop.
Photo web server in Go
package main
import (
"encoding/json"
"fmt"
"github.com/hoisie/web"
"github.com/mattn/go-session-manager"
"log"
"os"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"io"
"crypto/rand"
"encoding/hex"
"github.com/nfnt/resize"
"image/jpeg"
//"flag"
)
type AlbumForAdding struct {
Name string
Deleted bool
}
type AlbumForListing struct {
Id bson.ObjectId "_id"
Name string
Deleted bool
}
type Photo struct {
Path string
Description string
}
type Album struct {
Id bson.ObjectId "_id"
Name string
Photos []Photo
Deleted bool
}
type PhotoInfo struct {
Path string;
Type string;
}
type Bangbut struct {
DbSession *mgo.Session
PhotoDb *mgo.Database
logger *log.Logger
manager *session.SessionManager
}
func (app *Bangbut) getSession(ctx *web.Context) *session.Session {
id, _ := ctx.GetSecureCookie("SessionId")
app.logger.Printf("SESS ID = %v\n", id);
session := app.manager.GetSessionById(id)
app.logger.Println(session.Value)
ctx.SetSecureCookie("SessionId", session.Id, int64(app.manager.GetTimeout()))
ctx.SetHeader("Pragma", "no-cache", true)
return session
}
func (app *Bangbut) initDb () {
var err error
app.DbSession, err = mgo.Dial("localhost")
if err != nil {
panic(err)
}
app.DbSession.SetMode(mgo.Monotonic, true)
app.PhotoDb = app.DbSession.DB("photodb")
}
func (app *Bangbut) initSession () {
app.logger = log.New(os.Stdout, "", log.Ldate|log.Ltime)
app.manager = session.NewSessionManager(app.logger)
app.manager.OnStart(func(session *session.Session) {
app.logger.Printf("Start session(\"%s\")", session.Id)
})
app.manager.OnEnd(func(session *session.Session) {
app.logger.Printf("End session(\"%s\")", session.Id)
})
app.manager.SetTimeout(100000)
}
func (app *Bangbut) private (ctx *web.Context) {
session := app.getSession(ctx)
if session.Value != nil {
ctx.WriteString("DONE")
} else {
ctx.Abort(401, "Permission deny")
}
}
func (app *Bangbut) albums (ctx *web.Context) {
session := app.getSession(ctx)
app.logger.Println(session.Value)
i := app.PhotoDb.C("album").Find(bson.M{"deleted": false}).Iter()
var album_names []AlbumForListing
err := i.All(&album_names)
if err != nil {
ctx.Abort(500, "Internal server error")
} else {
album_json, err := json.Marshal(album_names)
if err != nil {
ctx.Abort(500, "Internal server error")
} else {
ctx.ContentType("application/json")
ctx.ResponseWriter.Write(album_json)
}
}
}
func (app *Bangbut) album (ctx *web.Context) {
session := app.getSession(ctx)
app.logger.Println(session.Value)
_id := ctx.Params["id"]
i := app.PhotoDb.C("album").Find(bson.M{"_id": bson.ObjectIdHex(_id)}).Iter()
var album Album
if i.Next(&album) {
album_json, err := json.Marshal(album)
if err != nil {
ctx.Abort(500, "Internal server error")
} else {
ctx.ContentType("application/json")
ctx.ResponseWriter.Write(album_json)
}
} else {
ctx.Abort(404, "Album not found")
}
}
func (app *Bangbut) login (ctx *web.Context) {
session := app.getSession(ctx)
app.logger.Println(session.Value)
ctx.Request.ParseForm()
username := ctx.Params["username"]
password := ctx.Params["password"]
if Auth(app.PhotoDb, username, password) {
session.Value = username
ctx.WriteString("Login")
} else {
ctx.Abort(401, "Permission deny")
}
}
func (app *Bangbut) add_album (ctx *web.Context) {
session := app.getSession(ctx)
app.logger.Println(session.Value)
if session.Value == nil {
ctx.Abort(401, "Permission deny")
return
}
album := AlbumForAdding{"New album", false}
err := app.PhotoDb.C("album").Insert(album)
if err != nil {
app.logger.Println(fmt.Sprintf("%v", err))
ctx.Abort(500, "Internal server error")
} else {
ctx.WriteString("DONE")
}
}
func (app *Bangbut) save_album (ctx *web.Context) {
session := app.getSession(ctx)
if session.Value == nil {
ctx.Abort(401, "Permission deny")
return
}
raw_album := ctx.Params["album"]
app.logger.Println("json = ", raw_album)
var album Album;
jsonErr := json.Unmarshal([]byte(raw_album), &album)
if jsonErr != nil {
app.logger.Println("Cannot convert JSON: ", jsonErr)
ctx.Abort(500, "Internal server error")
return
}
err := app.PhotoDb.C("album").UpdateId(album.Id, album)
if err != nil {
app.logger.Println("Cannot update")
ctx.Abort(500, "Internal server error")
return
}
ctx.WriteString("DONE")
}
func (app *Bangbut) delete_album (ctx *web.Context) {
session := app.getSession(ctx)
if session.Value == nil {
ctx.Abort(401, "Permission deny")
return
}
_id := ctx.Params["id"]
err := app.PhotoDb.C("album").Update(bson.M{"_id": bson.ObjectIdHex(_id)},
bson.M{"$set": bson.M{"deleted": true}})
if err == nil {
ctx.WriteString("DONE")
} else {
ctx.Abort(500, "Internal server error")
}
}
func resizeImage(filename string) error {
file, err := os.Open("static/photos/" + filename)
if err != nil {
return err
}
img, err := jpeg.Decode(file)
if err != nil {
return err
}
file.Close()
m := resize.Resize(300, 0, img, resize.Lanczos3)
out, err := os.Create("static/s/" + filename)
if err != nil {
return err
}
defer out.Close()
jpeg.Encode(out, m, nil)
return nil
}
func (app *Bangbut) upload (ctx *web.Context) {
session := app.getSession(ctx)
if session.Value == nil {
ctx.Abort(401, "Permission deny")
return
}
ctx.Request.ParseMultipartForm(10 * 1024 * 1024)
form := ctx.Request.MultipartForm
photoInfo := PhotoInfo{}
fileHeader := form.File["file"][0]
photoInfo.Type = fileHeader.Header["Content-Type"][0]
_, err := fileHeader.Open()
if err != nil {
app.logger.Println("Cannon open uploaded file");
ctx.Abort(500, "Internal server error")
return
}
buf := make([]byte, 32)
rand.Read(buf)
/* FIXME check type */
newFilename := hex.EncodeToString(buf) + ".jpg"
newFile, fileErr := os.Create("static/photos/" + newFilename)
if fileErr != nil {
app.logger.Println("Cannot open target file")
ctx.Abort(500, "Internal server error")
return
}
defer newFile.Close()
uploadedFile, uploadedFileErr := fileHeader.Open()
if uploadedFileErr != nil {
app.logger.Println("Cannot open uploaded file")
ctx.Abort(500, "Internal server error")
return
}
go func(file io.Reader, filename string) {
newFile, _ := os.Create("static/s/" + filename)
io.Copy(newFile, file)
newFile.Close()
}(uploadedFile, newFilename)
defer uploadedFile.Close()
photoInfo.Path = "/photos/" + newFilename
io.Copy(newFile, uploadedFile)
photoInfoJson, jsonErr := json.Marshal(photoInfo)
if jsonErr != nil {
ctx.Abort(500, "Internal server error")
return
}
ctx.ContentType("application/json")
ctx.ResponseWriter.Write(photoInfoJson)
}
func (app *Bangbut) logout (ctx *web.Context) {
session := app.getSession(ctx)
app.logger.Println(session.Value)
session.Abandon()
ctx.WriteString("* Logout");
}
func main() {
web.Config.CookieSecret = "SECRET" // Please change this
app := Bangbut{}
app.initDb()
app.initSession()
web.Post("/upload", app.upload)
web.Get("/private", app.private)
web.Get("/albums", app.albums)
web.Get("/album", app.album)
web.Get("/add_album", app.add_album)
web.Post("/save_album", app.save_album)
web.Get("/delete_album", app.delete_album)
web.Post("/login", app.login)
web.Get("/logout", app.logout)
web.Run("0.0.0.0:80")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment