diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ee6734..c5d662f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] - xxxx-xx-xx +### Fixed +- [#29](https://github.com/elyby/chrly/issues/29) If a previously cached UUID no longer exists, + it will be invalidated and re-requested. +- Use correct status code for error about empty response from Mojang's API. ## [4.5.0] - 2020-05-01 ### Added diff --git a/api/mojang/mojang.go b/api/mojang/mojang.go index c64179f..224c5ea 100644 --- a/api/mojang/mojang.go +++ b/api/mojang/mojang.go @@ -166,7 +166,7 @@ type EmptyResponse struct { } func (*EmptyResponse) Error() string { - return "200: Empty Response" + return "204: Empty Response" } func (*EmptyResponse) IsMojangError() bool { diff --git a/api/mojang/mojang_test.go b/api/mojang/mojang_test.go index 1a9162d..1b6ec31 100644 --- a/api/mojang/mojang_test.go +++ b/api/mojang/mojang_test.go @@ -261,7 +261,7 @@ func TestUuidToTextures(t *testing.T) { result, err := UuidToTextures("4566e69fc90748ee8d71d7ba5aa00d20", false) assert.Nil(result) assert.IsType(&EmptyResponse{}, err) - assert.EqualError(err, "200: Empty Response") + assert.EqualError(err, "204: Empty Response") assert.Implements((*ResponseError)(nil), err) }) diff --git a/mojangtextures/mojang_textures.go b/mojangtextures/mojang_textures.go index c5a3978..a5252d2 100644 --- a/mojangtextures/mojang_textures.go +++ b/mojangtextures/mojang_textures.go @@ -135,7 +135,8 @@ func (ctx *Provider) getResultAndBroadcast(username string, uuid string) { ctx.broadcaster.BroadcastAndRemove(username, result) } -func (ctx *Provider) getResult(username string, uuid string) *broadcastResult { +func (ctx *Provider) getResult(username string, cachedUuid string) *broadcastResult { + uuid := cachedUuid if uuid == "" { profile, err := ctx.getUuid(username) if err != nil { @@ -156,6 +157,12 @@ func (ctx *Provider) getResult(username string, uuid string) *broadcastResult { textures, err := ctx.getTextures(uuid) if err != nil { + // Previously cached UUIDs may disappear + // In this case we must invalidate UUID cache for given username + if _, ok := err.(*mojang.EmptyResponse); ok && cachedUuid != "" { + return ctx.getResult(username, "") + } + return &broadcastResult{nil, err} } diff --git a/mojangtextures/mojang_textures_test.go b/mojangtextures/mojang_textures_test.go index cbbb07e..4417d94 100644 --- a/mojangtextures/mojang_textures_test.go +++ b/mojangtextures/mojang_textures_test.go @@ -314,6 +314,42 @@ func (suite *providerTestSuite) TestGetForUsernameWhichHasMojangAccountButHasNoM suite.Assert().Nil(err) } +// https://github.com/elyby/chrly/issues/29 +func (suite *providerTestSuite) TestGetForUsernameWithCachedUuidThatHasBeenDisappeared() { + expectedErr := &mojang.EmptyResponse{} + expectedProfile := &mojang.ProfileInfo{Id: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", Name: "username"} + var nilTexturesResponse *mojang.SignedTexturesResponse + expectedResult := &mojang.SignedTexturesResponse{Id: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", Name: "username"} + + suite.Emitter.On("Emit", "mojang_textures:call", "username").Once() + suite.Emitter.On("Emit", "mojang_textures:usernames:before_cache", "username").Once() + suite.Emitter.On("Emit", "mojang_textures:usernames:after_cache", "username", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", true, nil).Once() + suite.Emitter.On("Emit", "mojang_textures:textures:before_cache", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").Once() + suite.Emitter.On("Emit", "mojang_textures:textures:after_cache", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", nilTexturesResponse, nil).Once() + suite.Emitter.On("Emit", "mojang_textures:before_result", "username", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").Once() + suite.Emitter.On("Emit", "mojang_textures:textures:before_call", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").Once() + suite.Emitter.On("Emit", "mojang_textures:textures:after_call", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", nilTexturesResponse, expectedErr).Once() + suite.Emitter.On("Emit", "mojang_textures:usernames:before_call", "username").Once() + suite.Emitter.On("Emit", "mojang_textures:usernames:after_call", "username", expectedProfile, nil).Once() + suite.Emitter.On("Emit", "mojang_textures:textures:before_call", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").Once() + suite.Emitter.On("Emit", "mojang_textures:textures:after_call", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", expectedResult, nil).Once() + suite.Emitter.On("Emit", "mojang_textures:after_result", "username", expectedResult, nil).Once() + + suite.Storage.On("GetUuid", "username").Once().Return("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", true, nil) + suite.Storage.On("GetTextures", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").Once().Return(nil, nil) + suite.Storage.On("StoreUuid", "username", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").Once().Return(nil) + suite.Storage.On("StoreTextures", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", expectedResult).Once() + + suite.UuidsProvider.On("GetUuid", "username").Return(expectedProfile, nil) + suite.TexturesProvider.On("GetTextures", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").Return(nil, expectedErr) + suite.TexturesProvider.On("GetTextures", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").Return(expectedResult, nil) + + result, err := suite.Provider.GetForUsername("username") + + suite.Assert().Nil(err) + suite.Assert().Equal(expectedResult, result) +} + func (suite *providerTestSuite) TestGetForTheSameUsernames() { expectedProfile := &mojang.ProfileInfo{Id: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Name: "username"} expectedResult := &mojang.SignedTexturesResponse{Id: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Name: "username"}