package hello
import (
"net/http"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
// our handler struct
type HelloHandler struct {
options *HelloHandlerOptions
}
// the handler's options that are passed
type HelloHandlerOptions struct {
ms *mgo.Session
db string
col string
prefix string
}
// the mongodb message type/struct
type Message struct {
Id bson.ObjectId `bson:"_id,omitempty"`
Name string `bson:",omitempty"`
Text string
}
// create new hellohandler convenience function
func NewHelloHandler(options *HelloHandlerOptions) *HelloHandler {
return &HelloHandler{
options: options,
}
}
// create new options convenience function
func NewHelloHandlerOptions(ms *mgo.Session, db, col, prefix string) *HelloHandlerOptions {
return &HelloHandlerOptions{
ms: ms.Clone(),
db: db,
col: col,
prefix: prefix,
}
}
// close the mgo connection
func (h *HelloHandler) Close() {
h.options.ms.Close()
}
// satify http.Handler interface
func (h *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
// display list of messages
h.Get(w, r)
case "POST":
// process post request and create a new message if valid
h.Post(w, r)
default:
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
}
}
// I named it Get() you could also name it ListMessages() but also rename h.Get(w, r) to h.ListMessages(w, r)
func (h *HelloHandler) Get(w http.ResponseWriter, r *http.Request) {
// copy the session
ms := h.options.ms.Copy()
defer ms.Close()
cMessage := ms.DB(h.options.db).C(h.options.col)
// create holder for messages
msgs := []*Message{}
// query
if e := cMessage.Find(nil).Sort("_id").All(&msgs); e != nil {
http.Error(w, e.Error(), http.StatusInternalServerError)
return
}
// create a template execution context
ctx := make(map[string]interface{})
ctx["Messages"] = msgs
// and render the template with context
if e := tplHelloIndex.Execute(w, ctx); e != nil {
// or return an error if there's an error in the template
http.Error(w, e.Error(), http.StatusInternalServerError)
}
}
func (h *HelloHandler) Post(w http.ResponseWriter, r *http.Request) {
name := r.FormValue("name")
message := r.FormValue("message")
if message == "" {
// since we're lazy return a http error
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
ms := h.options.ms.Copy()
defer ms.Close()
cMessage := ms.DB(h.options.db).C(h.options.col)
// create the message
msg := new(Message)
msg.Id = bson.NewObjectId()
msg.Name = name
msg.Text = message
// insert into database, if error return error
if e := cMessage.Insert(msg); e != nil {
http.Error(w, e.Error(), http.StatusInternalServerError)
return
}
// else redirect back to display page
http.Redirect(w, r, h.options.prefix, 302)
}