Skip to content

Commit 4e16f1c

Browse files
author
Zbynek Novotny
committed
Added match handler that dispatches match/* requests to subhandlers.
Also added New...() functions to handlers to hide their initialization process a little bit
1 parent 79b55c0 commit 4e16f1c

9 files changed

+118
-22
lines changed

TODO

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Nuffin' to see here
1+
Empty

handlers/leaderboard_handler.go

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ type LeaderboardHandler struct {
1212
core *core.Core
1313
}
1414

15+
// NewLeaderboardHandler returns a pointer
16+
// to a new leaderboard handler instance
17+
func NewLeaderboardHandler(c *core.Core) *LeaderboardHandler {
18+
return &LeaderboardHandler{core: c}
19+
}
20+
1521
// ProcessRequest process the client's request and prepares
1622
// an appropriate response
1723
func (h *LeaderboardHandler) ProcessRequest(resp http.ResponseWriter, req *http.Request) {

handlers/login_handler.go

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ type LoginHandler struct {
2323
core *core.Core
2424
}
2525

26+
// NewLoginHandler creates a pointer to a new
27+
// instance of the login request handler structure
28+
func NewLoginHandler(c *core.Core) *LoginHandler {
29+
return &LoginHandler{core: c}
30+
}
31+
2632
// ProcessRequest handles the login POST request
2733
func (h *LoginHandler) ProcessRequest(resp http.ResponseWriter, req *http.Request) {
2834
if req.Method != "POST" {

handlers/main_dispatcher.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import (
1010
// and distributes to them the incoming requests
1111
type MainDispatcher struct {
1212
core *core.Core
13-
login LoginHandler
14-
mlist MatchlistHandler
15-
lboard LeaderboardHandler
16-
mjoin MatchJoinHandler
13+
login *LoginHandler
14+
mlist *MatchlistHandler
15+
lboard *LeaderboardHandler
16+
match *MatchHandler
1717
// TODO Add join handler
1818
}
1919

@@ -22,10 +22,10 @@ type MainDispatcher struct {
2222
func NewMainDispatcher(c *core.Core) *MainDispatcher {
2323
return &MainDispatcher{
2424
core: c,
25-
login: LoginHandler{core: c},
26-
mlist: MatchlistHandler{core: c},
27-
lboard: LeaderboardHandler{core: c},
28-
mjoin: MatchJoinHandler{core: c},
25+
login: NewLoginHandler(c),
26+
mlist: NewMatchlistHandler(c),
27+
lboard: NewLeaderboardHandler(c),
28+
match: NewMatchHandler(c),
2929
}
3030
}
3131

@@ -41,7 +41,7 @@ func (dispatcher *MainDispatcher) ServeHTTP(resp http.ResponseWriter, req *http.
4141
case "leaderboards":
4242
dispatcher.lboard.ProcessRequest(resp, req)
4343
case "match":
44-
dispatcher.mjoin.ProcessRequest(resp, req)
44+
dispatcher.match.ProcessRequest(resp, req)
4545
default:
4646
http.Error(resp, "Resource not found", http.StatusNotFound)
4747
}

handlers/match_handler.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package handlers
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/mrclayman/rest_api_test/core"
7+
)
8+
9+
// MatchHandler structure represents a handler
10+
// processing REST/WS requests regarding match
11+
// joining and match event processing
12+
type MatchHandler struct {
13+
core *core.Core
14+
join *MatchJoinHandler
15+
room *MatchRoomHandler
16+
}
17+
18+
// NewMatchHandler returns a pointer to a new
19+
// instance of the match request handler
20+
func NewMatchHandler(c *core.Core) *MatchHandler {
21+
return &MatchHandler{
22+
core: c,
23+
join: NewMatchJoinHandler(c),
24+
room: NewMatchRoomHandler(c),
25+
}
26+
}
27+
28+
// ProcessRequest inspects the incoming request and dispatches it
29+
// further to individual handlers based on the type of the request
30+
func (h *MatchHandler) ProcessRequest(resp http.ResponseWriter, req *http.Request) {
31+
var action string
32+
switch action, req.URL.Path = SplitPath(req.URL.Path); action {
33+
case "join":
34+
h.join.ProcessRequest(resp, req)
35+
case "room":
36+
h.room.ProcessRequest(resp, req)
37+
default:
38+
http.Error(resp, "Resource '"+action+"' not found", http.StatusNotFound)
39+
}
40+
}

handlers/match_join_handler.go

+7-8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ type MatchJoinHandler struct {
2323
core *core.Core
2424
}
2525

26+
// NewMatchJoinHandler returns a pointer to a new
27+
// instance of the match join request handler
28+
func NewMatchJoinHandler(c *core.Core) *MatchJoinHandler {
29+
return &MatchJoinHandler{core: c}
30+
}
31+
2632
// ProcessRequest processes the user's request
2733
// and generates an appropriate response
2834
func (h *MatchJoinHandler) ProcessRequest(resp http.ResponseWriter, req *http.Request) {
@@ -31,14 +37,7 @@ func (h *MatchJoinHandler) ProcessRequest(resp http.ResponseWriter, req *http.Re
3137
return
3238
}
3339

34-
// Joining a match requires a reference to a particular
35-
// resource, check the URL to see if it is really there
36-
var action string
37-
action, req.URL.Path = SplitPath(req.URL.Path)
38-
if action != "join" {
39-
http.Error(resp, "Resource not found", http.StatusNotFound)
40-
return
41-
}
40+
4241

4342
// Parse and process the request
4443
var join joinRequest

handlers/match_room_handler.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package handlers
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/gorilla/websocket"
7+
"github.com/mrclayman/rest_api_test/core"
8+
)
9+
10+
// MatchRoomHandler handles WebSocket requests
11+
// from a player that has previously joined
12+
// a match
13+
type MatchRoomHandler struct {
14+
core *core.Core
15+
upgrader websocket.Upgrader
16+
}
17+
18+
// NewMatchRoomHandler returns a pointer to a
19+
// new instance of the match room request handler
20+
func NewMatchRoomHandler(c *core.Core) *MatchRoomHandler {
21+
return &MatchRoomHandler{
22+
core: c,
23+
upgrader: websocket.Upgrader{},
24+
}
25+
}
26+
27+
// ProcessRequest processes the WebSocket request
28+
// from the player and creates an appropriate response
29+
func (h *MatchRoomHandler) ProcessRequest(resp http.ResponseWriter, req *http.Request) {
30+
// Obtain the connection object from the request
31+
conn, err := h.upgrader.Upgrade(resp, req, nil)
32+
if err != nil {
33+
http.Error(resp, "Failed to obtain connection from request: "+err.Error(), http.StatusInternalServerError)
34+
}
35+
36+
defer conn.Close()
37+
38+
// TODO Finish the implementation
39+
}

handlers/matchlist_handler.go

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ type MatchlistHandler struct {
1212
core *core.Core
1313
}
1414

15+
// NewMatchlistHandler returns a pointer to a new
16+
// matchlist handler instance
17+
func NewMatchlistHandler(c *core.Core) *MatchlistHandler {
18+
return &MatchlistHandler{core: c}
19+
}
20+
1521
// ProcessRequest processes the incoming request and creates
1622
// an appropriate response
1723
func (h *MatchlistHandler) ProcessRequest(resp http.ResponseWriter, req *http.Request) {

handlers/util.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ func WriteJSONToResponse(resp http.ResponseWriter, in interface{}) error {
5959
return err
6060
}
6161

62-
// getSingleValueFromGetArgs obtains a single value from
62+
// getValueFromGET obtains a single value from
6363
// the request's GET arguments. It is expected that exactly
6464
// one value is present in the arguments and that the GET
6565
// arguments have been parsed beforehand using ParseForm()
66-
func getSingleValueFromGetArgs(req *http.Request, name string) (string, bool) {
66+
func getValueFromGET(req *http.Request, name string) (string, bool) {
6767
value := req.Form.Get(name)
6868
var ok bool
6969
if len(value) > 0 {
@@ -82,15 +82,15 @@ func GetPlayerDataFromGetArgs(req *http.Request) (core.PlayerID, core.AuthToken,
8282
token := core.InvalidAuthToken
8383
var err error
8484

85-
if strPlayerID, ok := getSingleValueFromGetArgs(req, "id"); !ok {
85+
if strPlayerID, ok := getValueFromGET(req, "id"); !ok {
8686
return core.InvalidPlayerID, core.InvalidAuthToken,
8787
RequestError{"Failed to obtain player ID from request"}
8888
} else if playerID, err = core.StringToPlayerID(strPlayerID); err != nil {
8989
return core.InvalidPlayerID, core.InvalidAuthToken,
9090
RequestError{"Failed to convert argument to player ID"}
9191
}
9292

93-
if strToken, ok := getSingleValueFromGetArgs(req, "token"); !ok {
93+
if strToken, ok := getValueFromGET(req, "token"); !ok {
9494
return core.InvalidPlayerID, core.InvalidAuthToken,
9595
RequestError{"Failed to obtain player's authentication token from request"}
9696
} else {

0 commit comments

Comments
 (0)