about summary refs log tree commit diff
path: root/src/http.go
blob: 9f9735241e46c2e349761ecad706fbe6fcbcd87b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main

import (
	"flag"
	"github.com/gorilla/mux"
	"net/http"
	"fmt"
	"strings"
	"io/ioutil"
	"time"
)

var (
	port *int
)

func registerHTTPFlags() {
	port = flag.Int("port", 8080, "The port for HTTP")
}

func runHTTPServer() (error) {
	r := mux.NewRouter()

	r.HandleFunc("/", indexHandler)
	r.HandleFunc("/files/{file}", fileHandler)
	r.HandleFunc("/login", loginGetHandler).Methods("GET")
	r.HandleFunc("/login", loginPostHandler).Methods("POST")
	r.HandleFunc("/logout", logoutHandler).Methods("GET")

	address := fmt.Sprintf(":%d", *port)
	return http.ListenAndServe(address, r)
}

// Host the index file
func indexHandler(w http.ResponseWriter, r *http.Request) {
	session, cookieNotFoundError := r.Cookie("session")

	if cookieNotFoundError != nil || !isValidSession(session.Value) {
		// either no session cookie found, or it contains an invalid session token. Redirect.
		http.Redirect(w, r, "/login", http.StatusTemporaryRedirect)
	} else {
		// valid session token found, redirect to frontpage
		readFileToResponse(w, "/index.html")
	}
}

// Static host files
func fileHandler(w http.ResponseWriter, r *http.Request) {
	readFileToResponse(w, mux.Vars(r)["file"])
}

// Helper function to host files off of "hosted/" directory
func readFileToResponse(w http.ResponseWriter, path string) {
	requestedFile := strings.Replace(path, "..", "", -1)

	contents, readError := ioutil.ReadFile(fmt.Sprintf("hosted/%s", requestedFile))

	if readError != nil {
		w.Write([]byte(fmt.Sprintf("unable to read %s", requestedFile)))
	} else {
		w.Write([]byte(contents))
	}
}

// Read login page
func loginGetHandler(w http.ResponseWriter, r *http.Request) {
	session, cookieNotFoundError := r.Cookie("session")

	// we need to verify that the client doesn't already have a valid session
	if cookieNotFoundError == nil && isValidSession(session.Value) {
		// session already valid, redirect the user
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
	} else {
		readFileToResponse(w, "/login.html")
	}
}

// Process login data
func loginPostHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	username := r.Form.Get("username")
	accessCode := r.Form.Get("accesscode")
	session, cookieNotFoundError := r.Cookie("session")

	validRedirect := false

	// we need to verify that the client doesn't already have a valid session
	if cookieNotFoundError == nil && isValidSession(session.Value) {
		// session already valid, redirect the user
		validRedirect = true
	} else {
		// no valid session present, check the given credentials

		if verifyCredentials(username, accessCode) {
			// credentials valid, create session
			newSessionToken := createSession()
			http.SetCookie(w, &http.Cookie{
				Name: "session",
				Value: newSessionToken,
				Path: "/",
				Expires: time.Now().Add(time.Hour * 24),
			})
			validRedirect = true
		}
	}

	if validRedirect {
		// Redirect to frontpage
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
		return
	} else {
		// credentials invalid or database error occured
		w.Write([]byte("Wrong credentials"))
		return
	}

	// Something else weird happened.
	w.WriteHeader(500)
	w.Write([]byte("Server Error"))
}

// Process logout and deletion of cookie
func logoutHandler(w http.ResponseWriter, r *http.Request) {
	session, cookieNotFoundError := r.Cookie("session")

	if cookieNotFoundError == nil {
		// cookie was found
		if isValidSession(session.Value) {
			// and it contains a valid session. Delete the session...
			destroySession(session.Value)
		}

		// and delete the cookie
		http.SetCookie(w, &http.Cookie{
			Name: "session",
			Value: "",
			Path: "/",
			Expires: time.Unix(0, 0),
		})
	}

	http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
}