Skip to content
This repository was archived by the owner on Aug 18, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/nodeagent/nodeagentmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ func (n *NodeAgentManager) heartbeatHandler(w http.ResponseWriter, r *http.Reque
ctx := context.Background()
re := regexp.MustCompile(`.*/v1/sessionHosts\/(.*?)(/heartbeats|$)`)
match := re.FindStringSubmatch(r.RequestURI)
if match == nil {
badRequest(w, fmt.Errorf("invalid request URI"), "cannot parse game server name")
return
}

gameServerName := match[1]

Expand Down
14 changes: 14 additions & 0 deletions cmd/nodeagent/nodeagentmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ var _ = Describe("nodeagent tests", func() {
_, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
})
It("heartbeat with a request URI that does not match the expected pattern should return error", func() {
req := httptest.NewRequest(http.MethodPost, "/v1/sessionHosts/sessionHostID", nil)
// simulate a request URI that reaches the handler but does not contain the literal path
// (e.g. via a percent-encoded path), so the regex returns no match
req.RequestURI = "/%76%31/sessionHosts/sessionHostID"
w := httptest.NewRecorder()
n := NewNodeAgentManager(newDynamicInterface(), testNodeName, false, false, time.Now, true)
n.heartbeatHandler(w, req)
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusBadRequest))
_, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
})
It("heartbeat with empty fields should return error", func() {
hb := &HeartbeatRequest{}
b, _ := json.Marshal(hb)
Expand Down
1 change: 1 addition & 0 deletions pkg/operator/controllers/allocation_api_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ func (s *AllocationApiServer) handleAllocationRequest(w http.ResponseWriter, r *

if r.Method != http.MethodPost && r.Method != http.MethodPatch {
badRequestError(w, s.logger, errors.New("invalid method"), "Only POST and PATCH are accepted")
return
}

// Parse args
Expand Down
23 changes: 23 additions & 0 deletions pkg/operator/controllers/allocation_api_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,29 @@ var _ = Describe("allocation API service input validation tests", func() {
_, err := io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
})
It("GET method with a valid body should return error and not allocate", func() {
client := testNewSimpleK8sClient()
gs, err := testCreateGameServerAndBuild(client, gsName, buildName1, buildID1, "", mpsv1alpha1.GameServerStateStandingBy)
Expect(err).ToNot(HaveOccurred())
err = testCreatePod(client, gsName)
Expect(err).ToNot(HaveOccurred())
req := httptest.NewRequest(http.MethodGet, "/api/v1/allocate", bytes.NewBufferString(fmt.Sprintf("{\"sessionID\":\"%s\",\"buildID\":\"%s\"}", sessionID1, buildID1)))
w := httptest.NewRecorder()
h := NewAllocationApiServer(nil, client, allocationApiSvcPort)
h.gameServerQueue = NewGameServersQueue()
h.gameServerQueue.PushToQueue(&GameServerForQueue{
Name: gsName,
Namespace: "default",
BuildID: buildID1,
ResourceVersion: gs.ObjectMeta.ResourceVersion,
})
h.handleAllocationRequest(w, req)
res := w.Result()
defer res.Body.Close()
Expect(res.StatusCode).To(Equal(http.StatusBadRequest))
_, err = io.ReadAll(res.Body)
Expect(err).ToNot(HaveOccurred())
})
It("bad body should return error", func() {
req := httptest.NewRequest(http.MethodPost, "/api/v1/allocate", bytes.NewBufferString("{\"foo\":\"bar\"}"))
w := httptest.NewRecorder()
Expand Down
Loading