Skip to content

Commit

Permalink
#1: Handle Mojang's server errors too
Browse files Browse the repository at this point in the history
  • Loading branch information
erickskrauch committed Apr 20, 2019
1 parent c292140 commit a8bbacf
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 7 deletions.
17 changes: 14 additions & 3 deletions api/mojang/mojang.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,13 @@ func UuidToTextures(uuid string, signed bool) (*SignedTexturesResponse, error) {
}

func validateResponse(response *http.Response) error {
switch response.StatusCode {
case 204:
switch {
case response.StatusCode == 204:
return &EmptyResponse{}
case 429:
case response.StatusCode == 429:
return &TooManyRequestsError{}
case response.StatusCode >= 500:
return &ServerError{response.StatusCode}
}

return nil
Expand All @@ -115,3 +117,12 @@ type TooManyRequestsError struct {
func (*TooManyRequestsError) Error() string {
return "Too Many Requests"
}

// ServerError happens when Mojang's API returns any response with 50* status
type ServerError struct {
Status int
}

func (e *ServerError) Error() string {
return "Server error"
}
44 changes: 43 additions & 1 deletion api/mojang/mojang_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestUsernamesToUuids(t *testing.T) {
}
})

t.Run("handle too many requests error", func(t *testing.T) {
t.Run("handle too many requests response", func(t *testing.T) {
assert := testify.New(t)

defer gock.Off()
Expand All @@ -73,6 +73,27 @@ func TestUsernamesToUuids(t *testing.T) {
assert.IsType(&TooManyRequestsError{}, err)
assert.EqualError(err, "Too Many Requests")
})

t.Run("handle server error", func(t *testing.T) {
assert := testify.New(t)

defer gock.Off()
gock.New("https://api.mojang.com").
Post("/profiles/minecraft").
Reply(500).
BodyString("500 Internal Server Error")

client := &http.Client{}
gock.InterceptClient(client)

HttpClient = client

result, err := UsernamesToUuids([]string{"Thinkofdeath", "maksimkurb"})
assert.Nil(result)
assert.IsType(&ServerError{}, err)
assert.EqualError(err, "Server error")
assert.Equal(500, err.(*ServerError).Status)
})
}

func TestUuidToTextures(t *testing.T) {
Expand Down Expand Up @@ -188,4 +209,25 @@ func TestUuidToTextures(t *testing.T) {
assert.IsType(&TooManyRequestsError{}, err)
assert.EqualError(err, "Too Many Requests")
})

t.Run("handle server error", func(t *testing.T) {
assert := testify.New(t)

defer gock.Off()
gock.New("https://sessionserver.mojang.com").
Get("/session/minecraft/profile/4566e69fc90748ee8d71d7ba5aa00d20").
Reply(500).
BodyString("500 Internal Server Error")

client := &http.Client{}
gock.InterceptClient(client)

HttpClient = client

result, err := UuidToTextures("4566e69fc90748ee8d71d7ba5aa00d20", false)
assert.Nil(result)
assert.IsType(&ServerError{}, err)
assert.EqualError(err, "Server error")
assert.Equal(500, err.(*ServerError).Status)
})
}
5 changes: 2 additions & 3 deletions api/mojang/queue/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (ctx *JobsQueue) queueRound() {

profiles, err := usernamesToUuids(usernames)
switch err.(type) {
case *mojang.TooManyRequestsError:
case *mojang.TooManyRequestsError, *mojang.ServerError:
for _, job := range jobs {
job.RespondTo <- nil
}
Expand Down Expand Up @@ -147,8 +147,7 @@ func (ctx *JobsQueue) getTextures(uuid string) *mojang.SignedTexturesResponse {
shouldCache := true
result, err := uuidToTextures(uuid, true)
switch err.(type) {
case *mojang.EmptyResponse:
case *mojang.TooManyRequestsError:
case *mojang.EmptyResponse, *mojang.TooManyRequestsError, *mojang.ServerError:
shouldCache = false
case error:
panic(err)
Expand Down
32 changes: 32 additions & 0 deletions api/mojang/queue/queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,18 @@ func (suite *QueueTestSuite) TestHandleTooManyRequestsResponseWhenExchangingUser
suite.Assert().Nil(<-resultChan)
}

func (suite *QueueTestSuite) TestHandleServerErrorWhenExchangingUsernamesToUuids() {
suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", &ValueNotFound{})
// Storage.StoreUuid, Storage.GetTextures and Storage.StoreTextures shouldn't be called
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return(nil, &mojang.ServerError{Status: 500})

resultChan := suite.Queue.GetTexturesForUsername("maksimkurb")

suite.Iterate()

suite.Assert().Nil(<-resultChan)
}

func (suite *QueueTestSuite) TestHandleEmptyResponseWhenRequestingUsersTextures() {
suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", &ValueNotFound{})
suite.Storage.On("StoreUuid", "maksimkurb", "0d252b7218b648bfb86c2ae476954d32").Once()
Expand Down Expand Up @@ -345,6 +357,26 @@ func (suite *QueueTestSuite) TestHandleTooManyRequestsResponseWhenRequestingUser
suite.Assert().Nil(<-resultChan)
}

func (suite *QueueTestSuite) TestHandleServerErrorWhenRequestingUsersTextures() {
suite.Storage.On("GetUuid", "maksimkurb").Once().Return("", &ValueNotFound{})
suite.Storage.On("StoreUuid", "maksimkurb", "0d252b7218b648bfb86c2ae476954d32").Once()
suite.Storage.On("GetTextures", "0d252b7218b648bfb86c2ae476954d32").Once().Return(nil, &ValueNotFound{})
// Storage.StoreTextures shouldn't be called
suite.MojangApi.On("UsernameToUuids", []string{"maksimkurb"}).Once().Return([]*mojang.ProfileInfo{
{Id: "0d252b7218b648bfb86c2ae476954d32", Name: "maksimkurb"},
}, nil)
suite.MojangApi.On("UuidToTextures", "0d252b7218b648bfb86c2ae476954d32", true).Once().Return(
nil,
&mojang.ServerError{Status: 500},
)

resultChan := suite.Queue.GetTexturesForUsername("maksimkurb")

suite.Iterate()

suite.Assert().Nil(<-resultChan)
}

func (suite *QueueTestSuite) TestReceiveTexturesForNotAllowedMojangUsername() {
resultChan := suite.Queue.GetTexturesForUsername("Not allowed")
suite.Assert().Nil(<-resultChan)
Expand Down

0 comments on commit a8bbacf

Please sign in to comment.