|
@@ -10,6 +10,8 @@ import (
|
|
"log"
|
|
"log"
|
|
"math/rand"
|
|
"math/rand"
|
|
"strconv"
|
|
"strconv"
|
|
|
|
+ "html/template"
|
|
|
|
+ "sort"
|
|
|
|
|
|
_ "github.com/go-sql-driver/mysql"
|
|
_ "github.com/go-sql-driver/mysql"
|
|
|
|
|
|
@@ -27,11 +29,14 @@ const (
|
|
maxConnectionCount = 256
|
|
maxConnectionCount = 256
|
|
|
|
|
|
helloWorldString = "Hello, World!"
|
|
helloWorldString = "Hello, World!"
|
|
|
|
+ extraFortuneMessage = "Additional fortune added at request time."
|
|
)
|
|
)
|
|
|
|
|
|
var (
|
|
var (
|
|
// Templates
|
|
// Templates
|
|
- // tmpl = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))
|
|
|
|
|
|
+ tmpl = template.Must(template.
|
|
|
|
+ ParseFiles("templates/layout.html",
|
|
|
|
+ "templates/fortune.html"))
|
|
|
|
|
|
// Database
|
|
// Database
|
|
worldStatement *sql.Stmt
|
|
worldStatement *sql.Stmt
|
|
@@ -54,6 +59,29 @@ func randomRow() *sql.Row {
|
|
return worldStatement.QueryRow(rand.Intn(worldRowCount) + 1)
|
|
return worldStatement.QueryRow(rand.Intn(worldRowCount) + 1)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+type Fortune struct {
|
|
|
|
+ Id uint16 `json:"id"`
|
|
|
|
+ Message string `json:"message"`
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type Fortunes []*Fortune
|
|
|
|
+
|
|
|
|
+func (s Fortunes) Len() int {
|
|
|
|
+ return len(s)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (s Fortunes) Swap(i, j int) {
|
|
|
|
+ s[i], s[j] = s[j], s[i]
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type ByMessage struct {
|
|
|
|
+ Fortunes
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (s ByMessage) Less(i, j int) bool {
|
|
|
|
+ return s.Fortunes[i].Message < s.Fortunes[j].Message
|
|
|
|
+}
|
|
|
|
+
|
|
// Test 1: Json Serialization
|
|
// Test 1: Json Serialization
|
|
func serializeJson(c web.C, w http.ResponseWriter, r *http.Request) {
|
|
func serializeJson(c web.C, w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Header().Set("Content-Type", "application/json")
|
|
@@ -98,6 +126,31 @@ func multipleQueries(c web.C, w http.ResponseWriter, r *http.Request) {
|
|
json.NewEncoder(w).Encode(worlds)
|
|
json.NewEncoder(w).Encode(worlds)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Test 4: Fortunes
|
|
|
|
+func fortunes(c web.C, w http.ResponseWriter, r *http.Request) {
|
|
|
|
+ rows, err := fortuneStatement.Query()
|
|
|
|
+ if err != nil {
|
|
|
|
+ log.Fatalf("Error preparing statement: %v", err)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fortunes := make(Fortunes, 0, 16)
|
|
|
|
+
|
|
|
|
+ for rows.Next() {
|
|
|
|
+ fortune := Fortune{}
|
|
|
|
+ if err := rows.Scan(&fortune.Id, &fortune.Message); err != nil {
|
|
|
|
+ log.Fatalf("Error scanning fortune row: %s", err.Error())
|
|
|
|
+ }
|
|
|
|
+ fortunes = append(fortunes, &fortune)
|
|
|
|
+ }
|
|
|
|
+ fortunes = append(fortunes, &Fortune{Message: extraFortuneMessage})
|
|
|
|
+
|
|
|
|
+ sort.Sort(ByMessage{fortunes})
|
|
|
|
+ w.Header().Set("Content-Type", "text/html")
|
|
|
|
+ if err := tmpl.Execute(w, fortunes); err != nil {
|
|
|
|
+ http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
// Test 6: Plaintext
|
|
// Test 6: Plaintext
|
|
func plaintext(c web.C, w http.ResponseWriter, r *http.Request) {
|
|
func plaintext(c web.C, w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprintf(w, "Hello, World!")
|
|
fmt.Fprintf(w, "Hello, World!")
|
|
@@ -128,6 +181,7 @@ func main() {
|
|
goji.Get("/json", serializeJson)
|
|
goji.Get("/json", serializeJson)
|
|
goji.Get("/db", singleQuery)
|
|
goji.Get("/db", singleQuery)
|
|
goji.Get("/queries", multipleQueries)
|
|
goji.Get("/queries", multipleQueries)
|
|
|
|
+ goji.Get("/fortunes", fortunes)
|
|
goji.Get("/plaintext", plaintext)
|
|
goji.Get("/plaintext", plaintext)
|
|
goji.Serve()
|
|
goji.Serve()
|
|
}
|
|
}
|