Skip to content

Instantly share code, notes, and snippets.

@jdkruzr
Created July 8, 2016 15:49
Show Gist options
  • Save jdkruzr/f6a8cf479fa7217af87767273aa2a61c to your computer and use it in GitHub Desktop.
Save jdkruzr/f6a8cf479fa7217af87767273aa2a61c to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"strings"
"time"
"crypto/md5"
"io"
"os"
"strconv"
"sync"
"crypto/rand"
"encoding/base64"
"net/url"
)
type Manager struct {
cookieName string //private cookiename
lock sync.Mutex //protects session
provider Provider
maxlifetime int64
}
type Provider interface {
SessionInit(sid string) (Session, error)
SessionRead(sid string) (Session, error)
SessionDestroy(sid string) error
SessionGC(maxLifeTime int64)
}
type Session interface {
Set(key, value interface{}) error //set session value
Get(key interface{}) interface{} //get session value
Delete(key interface{}) error //delete session value
SessionID() string
}
var provides = make(map[string]Provider)
//Register makes a session provider available by the provided name.
//If a Register is called twice with the same name or the driver is nil,
//it panics.
func Register(name string, provider Provider) {
if provider == nil {
panic("session: Register provider is nil")
}
if _, dup := provides[name]; dup {
panic("session: Register called twice for provider " + name)
}
provides[name] = provider
}
func (manager *Manager) sessionId() string {
b := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return ""
}
return base64.URLEncoding.EncodeToString(b)
}
func NewManager(provideName, cookieName string, maxlifetime int64) (*Manager, error) {
provider, ok := provides[provideName]
if !ok {
return nil, fmt.Errorf("session: unknown provide %q (forgotten import?)", provideName)
}
return &Manager{provider: provider, cookieName: cookieName, maxlifetime: maxlifetime}, nil
}
func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session Session) {
manager.lock.Lock()
defer manager.lock.Unlock()
cookie, err := r.Cookie(manager.cookieName)
if err != nil || cookie.Value == "" {
sid := manager.sessionId()
session, _ = manager.provider.SessionInit(sid)
cookie := http.Cookie{Name: manager.cookieName, Value: url.QueryEscape(sid), Path: "/", HttpOnly: true, MaxAge: int(manager.maxlifetime)}
http.SetCookie(w, &cookie)
} else {
sid, _ := url.QueryUnescape(cookie.Value)
session, _ = manager.provider.SessionRead(sid)
}
return
}
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //parse URL parameters and then the contents of the POST
fmt.Println("path: ", r.URL.Path)
fmt.Println("scheme: ", r.URL.Scheme)
fmt.Println(r.Form, "\n")
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key: ", k)
fmt.Println("val: ", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello @radiofreekruzr!") // Write this to response
}
func login(w http.ResponseWriter, r *http.Request) {
sess := globalSessions.SessionStart(w, r)
r.ParseForm()
if r.Method == "GET" {
t, _ := template.ParseFiles("login.gtpl")
w.Header().Set("Content-Type", "text/html")
t.Execute(w, sess.Get("username"))
} else {
sess.Set("username", r.Form["username"])
http.Redirect(w, r, "/", 302)
}
}
func upload(w http.ResponseWriter, r *http.Request) {
fmt.Println("method: ", r.Method)
if r.Method == "GET" {
crutime := time.Now().Unix()
h := md5.New()
io.WriteString(h, strconv.FormatInt(crutime, 10))
token := fmt.Sprintf("%x", h.Sum(nil))
t, _ := template.ParseFiles("upload.gtpl")
t.Execute(w, token)
} else {
r.ParseMultipartForm(32 << 20)
file, handler, err := r.FormFile("uploadfile")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
fmt.Fprintf(w, "%v", handler.Header)
f, err := os.OpenFile("./test/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
io.Copy(f, file)
}
}
func count(w http.ResponseWriter, r *http.Request) {
sess := globalSessions.SessionStart(w, r)
createtime := sess.Get("createtime")
if createtime == nil {
sess.Set("createtime", time.Now().Unix())
} else if (createtime.(int64) + 360) < (time.Now().Unix()) {
globalSessions.SessionDestroy(w, r)
sess = globalSessions.SessionStart(w, r)
}
ct := sess.Get("countnum")
if ct == nil {
sess.Set("countnum", 1)
} else {
sess.Set("countnum", (ct.(int) + 1))
}
t, _ := template.ParseFiles("count.gtpl")
w.Header().Set("Content-Type", "text/html")
t.Execute(w, sess.Get("countnum"))
}
//Destroy sessionid
func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request){
cookie, err := r.Cookie(manager.cookieName)
if err != nil || cookie.Value == "" {
return
} else {
manager.lock.Lock()
defer manager.lock.Unlock()
manager.provider.SessionDestroy(cookie.Value)
expiration := time.Now()
cookie := http.Cookie{Name: manager.cookieName, Path: "/", HttpOnly: true, Expires: expiration, MaxAge: -1}
http.SetCookie(w, &cookie)
}
}
func (manager *Manager) GC() {
manager.lock.Lock()
defer manager.lock.Unlock()
manager.provider.SessionGC(manager.maxlifetime)
time.AfterFunc(time.Duration(manager.maxlifetime), func() { manager.GC() })
}
func main() {
var globalSessions *session.Manager
// Then, initialize the session manager
func init() {
globalSessions = NewManager("memory","gosessionid",3600)
}
go globalSessions.GC()
http.HandleFunc("/", sayhelloName)
http.HandleFunc("/login", login)
http.HandleFunc("/upload", upload)
err := http.ListenAndServe(":3001", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
@jdkruzr
Copy link
Author

jdkruzr commented Jul 8, 2016

Here's the error when I compile:

[Fri Jul 08 11:44:37 jtd@gruis ~/work-go/playground]$ go build forms.go

command-line-arguments

./forms.go:187: syntax error: unexpected init, expecting (
./forms.go:188: syntax error: unexpected globalSessions
./forms.go:191: syntax error: non-declaration statement outside function body

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment