Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "database/sql"
- "errors"
- "github.com/bradfitz/gomemcache/memcache"
- _ "github.com/go-sql-driver/mysql"
- "html"
- "log"
- "net/http"
- "runtime"
- "strconv"
- "strings"
- )
- const (
- listen = "127.0.0.1:12345"
- mysqlConnection = "dbuser:dbpass@tcp(dbhost:3306)/dbname"
- maxConnectionCount = 256
- storySelect = "SELECT data FROM stories WHERE id = ?"
- )
- var (
- storyStatement *sql.Stmt
- memcachedConnection = []string{"10.0.0.1:11211", "10.0.0.2:11211", "10.0.0.3:11212"}
- mc *memcache.Client
- pong_str = []byte("pong: ")
- )
- func main() {
- runtime.GOMAXPROCS(runtime.NumCPU())
- mc = memcache.New(memcachedConnection...)
- db, err := sql.Open("mysql", mysqlConnection)
- if err != nil {
- log.Fatalf("Error opening database: %v", err)
- }
- db.SetMaxIdleConns(maxConnectionCount)
- storyStatement, err = db.Prepare(storySelect)
- if err != nil {
- log.Fatal(err)
- }
- http.HandleFunc("/ping", pingHandler)
- http.HandleFunc("/story/", storyHandler)
- http.ListenAndServe(listen, nil)
- }
- func pingHandler(w http.ResponseWriter, r *http.Request) {
- var rNum uint64
- var err error
- if rStr := r.URL.Query().Get("r"); len(rStr) > 0 {
- rNum, err = strconv.ParseUint(rStr, 10, 0)
- } else {
- err = errors.New("r parametr do not exist")
- }
- if err != nil {
- w.Header().Set("Content-Type", "text/plain")
- w.WriteHeader(404)
- w.Write([]byte(err.Error()))
- return
- }
- rNum++
- w.Header().Set("Content-Type", "text/plain")
- w.Write(strconv.AppendUint(pong_str, rNum, 10))
- }
- func storyHandler(w http.ResponseWriter, r *http.Request) {
- var story_id uint64
- var story_id_str string
- var err error
- if rStr, story_len := r.URL.Path, len("/story/"); len(rStr) > story_len {
- story_id_str = rStr[story_len:]
- story_id, err = strconv.ParseUint(story_id_str, 10, 0)
- } else {
- err = errors.New("Story Id do not exist")
- }
- if err != nil {
- w.Header().Set("Content-Type", "text/plain")
- w.WriteHeader(404)
- w.Write([]byte(err.Error()))
- return
- }
- w.Header().Set("Content-Type", "text/html")
- var story []byte
- if item, err := mc.Get(story_id_str); err != nil || len(item.Value) == 0 {
- var story_str string
- err = storyStatement.QueryRow(story_id).Scan(&story_str)
- if err != nil {
- log.Printf("Error scanning story row. Id:%d, erroro: %s", story_id, err.Error())
- story = []byte("Story not fount")
- w.WriteHeader(404)
- } else {
- story_str = html.EscapeString(story_str)
- strings.Replace(story_str, "\n", "<br>", -1)
- story = []byte(story_str) // ToDo избавиться от копирования памяти и от лишней переменной story_str
- }
- err = mc.Set(&memcache.Item{Key: story_id_str, Value: story, Expiration:1}) // ToDo использовать item из Get(), если он не nil
- if err != nil {
- log.Printf("Can not set key: %s", err.Error())
- }
- } else {
- story = item.Value
- }
- // ToDo переписать через append() или var buffer bytes.Buffer + buffer.WriteString(s2)
- w.Write([]byte("<!doctype html>\n<html>\n<head>\n<title>Story " + story_id_str + "</title>\n</head>\n<body>"))
- w.Write(story)
- w.Write([]byte("</body>\n</html>"))
- }
Advertisement
Add Comment
Please, Sign In to add comment