Webcounter with cookies
This commit is contained in:
parent
b9344dcf82
commit
4dc2e681c4
1
.gitignore
vendored
1
.gitignore
vendored
@ -59,3 +59,4 @@ tpl-ex2/tpl-ex2
|
||||
tpl-ex3/tpl-ex3
|
||||
form-ex1/form-ex1
|
||||
form-ex2/form-ex2
|
||||
webcounter/webcounter
|
||||
|
83
webcounter/main.go
Normal file
83
webcounter/main.go
Normal file
@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"hash"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var TPL *template.Template
|
||||
|
||||
const (
|
||||
SECRET = "QDFuO2FyRHhGKEg5QlI4XDMlM2sK"
|
||||
COUNTER_COOKIE string = "counter"
|
||||
)
|
||||
|
||||
func displayPage(res http.ResponseWriter, req *http.Request) {
|
||||
count, cookie := updateCounter(req)
|
||||
http.SetCookie(res, cookie)
|
||||
TPL.Execute(res, count)
|
||||
}
|
||||
|
||||
func updateCounter(req *http.Request) (uint64, *http.Cookie) {
|
||||
count := fromCookie(req)
|
||||
count++
|
||||
val := toCookieVal(count)
|
||||
cookie := &http.Cookie{
|
||||
Name: COUNTER_COOKIE,
|
||||
Value: val,
|
||||
}
|
||||
return count, cookie
|
||||
}
|
||||
|
||||
func fromCookie(req *http.Request) uint64 {
|
||||
cookie, err := req.Cookie(COUNTER_COOKIE)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
sp := strings.Split(cookie.Value, "|")
|
||||
if len(sp) != 2 {
|
||||
return 0
|
||||
}
|
||||
c, err := strconv.Atoi(sp[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if !checkMac(sp[0], sp[1]) {
|
||||
return 0
|
||||
}
|
||||
return uint64(c)
|
||||
}
|
||||
|
||||
func checkMac(val string, macStr string) bool {
|
||||
var mac []byte
|
||||
fmt.Sscanf(macStr, "%x", &mac)
|
||||
return hmac.Equal(mac, cookieHash(val).Sum(nil))
|
||||
}
|
||||
|
||||
func cookieHash(val string) hash.Hash {
|
||||
mac := hmac.New(sha256.New, []byte(SECRET))
|
||||
mac.Write([]byte(val))
|
||||
return mac
|
||||
}
|
||||
|
||||
func toCookieVal(count uint64) string {
|
||||
val := strconv.FormatUint(count, 10)
|
||||
return val + "|" + fmt.Sprintf("%x", cookieHash(val).Sum(nil))
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
TPL, err = template.ParseFiles("tpl.html")
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
http.HandleFunc("/", displayPage)
|
||||
http.ListenAndServe(":9000", nil)
|
||||
}
|
8
webcounter/tpl.html
Normal file
8
webcounter/tpl.html
Normal file
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Webcounter</title></head>
|
||||
<body>
|
||||
<p>Number of visits: {{ . }}</p>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user