Как переопределить декоратор по умолчанию ("**") для определенного ресурса в сиесте? - PullRequest
0 голосов
/ 11 апреля 2019

Я пытаюсь использовать пакет Siesta swift с моим API на сервере.Мы настроили аутентификацию JWT с токенами доступа и обновления.Мы можем успешно пройти аутентификацию и получить новые токены доступа с помощью процедуры обновления.Но решение, которое мы приняли, выглядит немного взломанным.

Мы используем такие декораторы запросов

func init() {
       service.configure("**") {
            if let session = self.appSession {
                $0.headers["Authorization"] = "Bearer \(session.tokens.access)"
            }

            $0.decorateRequests {
                self.globalApiFailHandler(request: $1)
            }
        }

        service.configure(authRefreshResource) {
            if let session = self.appSession {
                $0.headers["Authorization-Refresh"] = "Bearer \(session.tokens.refresh)"
            }

            $0.decorateRequests {
                self.refreshTokenFailure(request: $1)
            }
        }
}

private func globalApiFailHandler(request: Siesta.Request) -> Request {

        return request.chained {                    //special case to Refresh Token On Auth Failure
            if case
                .failure(let error) = $0.response,  // Did request fail…
                error.httpStatusCode == 401,        // …because of expired token?
                self.appSession != nil {            // we have refreshToken

                log.warning("Seems like Access Token is expired, Trying to refresh it!")
                return .passTo(
                    self.refreshAuth().chained {                  // first request a new token, then:
                        if case .failure = $0.response {          // If token request failed…
                            return .useThisResponse               // …report that error.
                        } else {
                            return .passTo(request.repeated())    // We have a new token! Repeat the original request.
                        }
                    }
                )

            }

            if case
                .failure(let error) = $0.response,
                error.httpStatusCode != 409 {

                log.warning("Something went wrong during request: \(error)")
                self.retryLaterEvent() // TODO: Really need this here?
            }

            return .useThisResponse                // If not, use the response we got.
        }
    }

    private func refreshTokenFailure(request: Siesta.Request) -> Request {
        return request.chained {
            if case
                .failure(let error) = $0.response {  // Did request fail…

                log.error("Refresh token procedure failed with \(error).")

                if error.httpStatusCode == 409 {
                    log.warning("409, Resetting app session storage! Relogin or app recreation is needed!")
                    self.relogin = true //Reset saved sessions to create new app
                    self.reloginEvent()
                } else {
                    log.warning("Something went wrong during refresh token procedure. Please retry later!")
                    self.retryLaterEvent()
                }

                ///let requestError  = RequestError(userMessage: "Unable to refresh access token", cause: "")
                let response = Response.failure(error) //(requestError)
                let responseInfo = ResponseInfo(response: response)

                return .useResponse(responseInfo)                // If not, use the response we got.
            }

            return .useThisResponse        // We have new token!
        }
    }

, обратите внимание 409 проверка кода возврата в globalApiFailHandler.Это происходит потому, что глобальный декоратор всегда вызывается для authRefreshResource.Если мы пропустим эту проверку, API застрянет в токене обновления бесконечного цикла при некоторых ошибках сервера.

Вопрос в том, как отключить глобальный декоратор для конкретного ресурса, который мы хотим?Наличие этого элегантно решит нашу проблему.

1 Ответ

0 голосов
/ 11 апреля 2019

Вы можете передать произвольный предикат на configure(whenURLMatches:), что позволит вам хирургическим путем исключить все, что вам нравится:

service.configure(whenURLMatches: { url in url.path != "/auth" }) {
    ...
}

Или, если, как в вашем случае, вы хотите исключить URL, для которого у вас есть Resource удобный:

service.configure(whenURLMatches: { $0 != authRefreshResource.url }) {
    ...
}
...