From b2a1fd450b93d876fb69e86aa65eea5886bd6e97 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Fri, 8 Nov 2019 01:32:26 +0300 Subject: [PATCH] Handle 403 Forbidden error from Mojang's API --- CHANGELOG.md | 2 ++ api/mojang/mojang.go | 11 +++++++++++ api/mojang/mojang_test.go | 21 +++++++++++++++++++++ api/mojang/queue/queue.go | 13 +++++++++---- api/mojang/queue/queue_test.go | 3 +++ 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 530d916..5d95343 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ 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 +### Added +- 403 Forbidden errors from the Mojang's API are now logged ## [4.2.3] - 2019-10-03 ### Changed diff --git a/api/mojang/mojang.go b/api/mojang/mojang.go index dd4132f..14ec5d8 100644 --- a/api/mojang/mojang.go +++ b/api/mojang/mojang.go @@ -125,6 +125,8 @@ func validateResponse(response *http.Response) error { _ = json.Unmarshal(body, &decodedError) return &BadRequestError{ErrorType: decodedError.Error, Message: decodedError.Message} + case response.StatusCode == 403: + return &ForbiddenError{} case response.StatusCode == 429: return &TooManyRequestsError{} case response.StatusCode >= 500: @@ -166,6 +168,15 @@ func (*BadRequestError) IsMojangError() bool { return true } +// When Mojang decides you're such a bad guy, this error appears (even if the request has no authorization) +type ForbiddenError struct { + ResponseError +} + +func (*ForbiddenError) Error() string { + return "Forbidden" +} + // When you exceed the set limit of requests, this error will be returned type TooManyRequestsError struct { ResponseError diff --git a/api/mojang/mojang_test.go b/api/mojang/mojang_test.go index 969f7ed..2bffc81 100644 --- a/api/mojang/mojang_test.go +++ b/api/mojang/mojang_test.go @@ -102,6 +102,27 @@ func TestUsernamesToUuids(t *testing.T) { assert.Implements((*ResponseError)(nil), err) }) + t.Run("handle forbidden response", func(t *testing.T) { + assert := testify.New(t) + + defer gock.Off() + gock.New("https://api.mojang.com"). + Post("/profiles/minecraft"). + Reply(403). + BodyString("just because") + + client := &http.Client{} + gock.InterceptClient(client) + + HttpClient = client + + result, err := UsernamesToUuids([]string{"Thinkofdeath", "maksimkurb"}) + assert.Nil(result) + assert.IsType(&ForbiddenError{}, err) + assert.EqualError(err, "Forbidden") + assert.Implements((*ResponseError)(nil), err) + }) + t.Run("handle too many requests response", func(t *testing.T) { assert := testify.New(t) diff --git a/api/mojang/queue/queue.go b/api/mojang/queue/queue.go index 3eb4d8e..1aa5241 100644 --- a/api/mojang/queue/queue.go +++ b/api/mojang/queue/queue.go @@ -182,13 +182,18 @@ func (ctx *JobsQueue) handleResponseError(err error, threadName string) { switch err.(type) { case mojang.ResponseError: - if _, ok := err.(*mojang.TooManyRequestsError); ok { - ctx.Logger.Warning(":name: Got 429 Too Many Requests :err", wd.NameParam(threadName), wd.ErrParam(err)) + if _, ok := err.(*mojang.BadRequestError); ok { + ctx.Logger.Warning(":name: Got 400 Bad Request :err", wd.NameParam(threadName), wd.ErrParam(err)) return } - if _, ok := err.(*mojang.BadRequestError); ok { - ctx.Logger.Warning(":name: Got 400 Bad Request :err", wd.NameParam(threadName), wd.ErrParam(err)) + if _, ok := err.(*mojang.ForbiddenError); ok { + ctx.Logger.Warning(":name: Got 403 Forbidden :err", wd.NameParam(threadName), wd.ErrParam(err)) + return + } + + if _, ok := err.(*mojang.TooManyRequestsError); ok { + ctx.Logger.Warning(":name: Got 429 Too Many Requests :err", wd.NameParam(threadName), wd.ErrParam(err)) return } diff --git a/api/mojang/queue/queue_test.go b/api/mojang/queue/queue_test.go index 6c1e5d6..f597a69 100644 --- a/api/mojang/queue/queue_test.go +++ b/api/mojang/queue/queue_test.go @@ -403,6 +403,7 @@ func (*timeoutError) Temporary() bool { return false } var expectedErrors = []error{ &mojang.BadRequestError{}, + &mojang.ForbiddenError{}, &mojang.TooManyRequestsError{}, &mojang.ServerError{}, &timeoutError{}, @@ -418,6 +419,7 @@ func (suite *queueTestSuite) TestShouldNotLogErrorWhenExpectedErrorReturnedFromU suite.Logger.On("RecordTimer", mock.Anything, mock.Anything) suite.Logger.On("Debug", ":name: Got response error :err", mock.Anything, mock.Anything).Times(len(expectedErrors)) suite.Logger.On("Warning", ":name: Got 400 Bad Request :err", mock.Anything, mock.Anything).Once() + suite.Logger.On("Warning", ":name: Got 403 Forbidden :err", mock.Anything, mock.Anything).Once() suite.Logger.On("Warning", ":name: Got 429 Too Many Requests :err", mock.Anything, mock.Anything).Once() suite.Storage.On("GetUuid", "maksimkurb").Return("", &ValueNotFound{}) @@ -455,6 +457,7 @@ func (suite *queueTestSuite) TestShouldNotLogErrorWhenExpectedErrorReturnedFromU suite.Logger.On("RecordTimer", mock.Anything, mock.Anything) suite.Logger.On("Debug", ":name: Got response error :err", mock.Anything, mock.Anything).Times(len(expectedErrors)) suite.Logger.On("Warning", ":name: Got 400 Bad Request :err", mock.Anything, mock.Anything).Once() + suite.Logger.On("Warning", ":name: Got 403 Forbidden :err", mock.Anything, mock.Anything).Once() suite.Logger.On("Warning", ":name: Got 429 Too Many Requests :err", mock.Anything, mock.Anything).Once() suite.Storage.On("GetUuid", "maksimkurb").Return("", &ValueNotFound{})