2

我正在尝试设置一个简单的 iOS 示例来更好地理解 Siesta。我的 REST api 需要一个访问令牌来伴随每个请求。因此,(1)在应用程序启动时和(2)每当我检索 HTTP 401 时,我都需要请求访问令牌,然后将其放入所有未来的授权标头中。

从文档中处理此示例,我假设包含的行showLoginScreen是我需要调用 myauthenticationResource以检索令牌的位置但是如何在之后立即进行失败的调用(当然不是无限循环)?谢谢你。

let authURL = authenticationResource.url

configure({ url in url != authURL }, description: "catch auth failures") {
  $0.config.beforeStartingRequest { _, req in  // For all resources except auth:
    req.onFailure { error in                     // If a request fails...
      if error.httpStatusCode == 401 {         // ...with a 401...
        showLoginScreen()                      // ...then prompt the user to log in
      }
    }
  }
}
4

1 回答 1

2

自从您提出问题以来,文档已更新为回答该问题的示例

它的关键是使用decorateRequests(…)Request.chained(…)包装所有服务的请求,以便它们在返回响应之前自动尝试刷新令牌。

以下是该示例中的代码:

authToken: String??

init() {
  ...
  configure("**", description: "auth token") {
    if let authToken = self.authToken {
      $0.headers["X-Auth-Token"] = authToken         // Set the token header from a var that we can update
    }
    $0.decorateRequests {
      self.refreshTokenOnAuthFailure(request: $1)
    }
  }
}

// Refactor away this pyramid of doom however you see fit
func refreshTokenOnAuthFailure(request: Request) -> Request {
  return request.chained {
    guard case .failure(let error) = $0.response,  // Did request fail…
      error.httpStatusCode == 401 else {           // …because of expired token?
        return .useThisResponse                    // If not, use the response we got.
    }

    return .passTo(
      self.createAuthToken().chained {             // If so, 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.
        }
      }
    )
  }
}

func createAuthToken() -> Request {
  return tokenCreationResource
    .request(.post, json: userAuthData())
    .onSuccess {
      self.authToken = $0.jsonDict["token"] as? String  // Store the new token, then…
      self.invalidateConfiguration()                    // …make future requests use it
    }
  }
}
于 2017-04-15T02:12:45.850 回答