-
Notifications
You must be signed in to change notification settings - Fork 0
/
handlers.go
155 lines (131 loc) · 3.89 KB
/
handlers.go
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
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"encoding/json"
"log"
"net/http"
"strconv"
"time"
)
// Servers the index page.
func IndexHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "html/index.html")
}
// Crete new user and redirects back to the IndexHandler on success.
func (c *Config) NewUserPostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
userName := r.PostForm.Get("user")
userPassword := r.PostForm.Get("password")
userPasswordConfirm := r.PostForm.Get("password_confirm")
if userName == "" || userPassword == "" {
http.Error(w, "missing user or password", http.StatusBadRequest)
return
}
if userPassword != userPasswordConfirm {
http.Error(w, "passwords do not match", http.StatusBadRequest)
return
}
if _, err := c.CreateUser(userName, userPassword); err != nil {
log.Printf("database query error: %q\n", err)
w.WriteHeader(http.StatusBadRequest)
return
}
// Publish message to send email
publishMail(userName)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
// Receives login requests and redirects to the APIChatHandler on success.
func (c *Config) LoginPostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
userName := r.PostForm.Get("user")
userPassword := r.PostForm.Get("password")
if userName == "" || userPassword == "" {
http.Error(w, "missing user or password", http.StatusBadRequest)
return
}
if err := c.CheckLogin(userName, userPassword); err != nil {
http.Error(w, "login unsuccessful", http.StatusBadRequest)
return
}
// Setup cookie with jwt token
token := c.MakeToken(userName)
http.SetCookie(w, &http.Cookie{
Name: "jwt",
Value: token,
})
http.Redirect(w, r, "/chat", http.StatusSeeOther)
}
// Serves the chat page.
func APIChatHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "html/chat.html")
}
// Retrieve messages to be displayed
func (c *Config) APIMessagesHandler(w http.ResponseWriter, r *http.Request) {
var (
err error
timeParam string
parsedTime int64 = time.Now().UnixNano() / 1e6 // To precision in mili seconds
order ByTime = older
attempts int = 1
)
r.ParseForm()
timeParam = r.Form.Get("before")
since := r.Form.Get("since")
if since != "" {
attempts = 10
order = newer
timeParam = since
}
if timeParam != "" {
if parsedTime, err = strconv.ParseInt(timeParam, 10, 64); err != nil {
http.Error(w, "invalid 'before' or 'since' parameter sent", http.StatusBadRequest)
}
}
var messages []Message
for i := 0; i < attempts; i++ {
messages, err = c.GetMessagesByTime(10, parsedTime, order)
if err != nil {
log.Printf("db failed to get messages: %q", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if len(messages) != 0 {
break
}
time.Sleep(1 * time.Second)
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
body, _ := json.Marshal(messages)
w.Write(body)
}
// Recieves a message and saves it.
func (c *Config) APIMessagesPostHandler(w http.ResponseWriter, r *http.Request) {
var message Message
var redirect bool
if r.Header.Get("Content-type") == "application/json" {
err := json.NewDecoder(r.Body).Decode(&message)
if err != nil {
http.Error(w, "malformed request body", http.StatusBadRequest)
return
}
} else { // In case the user disable javastrip on browser
r.ParseForm()
messageText := r.PostForm.Get("message")
if messageText == "" {
http.Error(w, "malformed request body", http.StatusBadRequest)
return
}
message.Text = messageText
redirect = true
}
userName := GetUserNameFromContext(r.Context())
if _, err := c.CreateMessage(userName, message.Text); err != nil {
log.Printf("db create message failure: %q", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if redirect { // If came from form, reload the chat is an easier solution
http.Redirect(w, r, "/chat", http.StatusSeeOther)
} else {
w.WriteHeader(http.StatusCreated)
}
}