bof*_*mer 5 dart dart-http flutter
我目前正在尝试访问 Flutter 中需要 JWT 访问令牌进行授权的 Web API。访问令牌在一定时间后过期。
可以使用单独的刷新令牌请求新的访问令牌。现在,只要请求返回 401 响应,就会执行此访问令牌刷新。之后,应使用新的访问令牌重试失败的请求。
我在这最后一步遇到了麻烦。好像http.BaseRequest只能发送一次。我将如何使用新令牌重试 http 请求?
正如dart http readme 中所建议的,我创建了一个子类http.BaseClient来添加授权行为。这是一个简化版本:
import 'dart:async';
import 'package:http/http.dart' as http;
class AuthorizedClient extends http.BaseClient {
AuthorizedClient(this._authService) : _inner = http.Client();
final http.Client _inner;
final AuthService _authService;
Future<http.StreamedResponse> send(http.BaseRequest request) async {
final token = await _authService.getAccessToken();
request.headers['Authorization'] = 'Bearer $token';
final response = await _inner.send(request);
if (response.statusCode == 401) {
final newToken = await _authService.refreshAccessToken();
request.headers['Authorization'] = 'Bearer $newToken';
// throws error: Bad state: Can't finalize a finalized Request
final retryResponse = await _inner.send(request);
return retryResponse;
}
return response;
}
}
abstract class AuthService {
Future<String> getAccessToken();
Future<String> refreshAccessToken();
}
Run Code Online (Sandbox Code Playgroud)
你不能两次send都一样BaseRequest。BaseRequest从第一个副本开始制作一个新副本,然后发送该副本。
这是一些用于“克隆” BaseRequest 的代码(来自 io_client)。
var copyRequest = await _inner.openUrl(request.method, request.url);
copyRequest
..followRedirects = request.followRedirects
..maxRedirects = request.maxRedirects
..contentLength = request.contentLength == null
? -1
: request.contentLength
..persistentConnection = request.persistentConnection;
request.headers.forEach((name, value) {
copyRequest.headers.set(name, value);
});
Run Code Online (Sandbox Code Playgroud)
这是我目前根据 Richard Heap 的回答得出的结论:要重新发送请求,我们必须复制它。
到目前为止,我无法提出流请求的解决方案!
http.BaseRequest _copyRequest(http.BaseRequest request) {
http.BaseRequest requestCopy;
if(request is http.Request) {
requestCopy = http.Request(request.method, request.url)
..encoding = request.encoding
..bodyBytes = request.bodyBytes;
}
else if(request is http.MultipartRequest) {
requestCopy = http.MultipartRequest(request.method, request.url)
..fields.addAll(request.fields)
..files.addAll(request.files);
}
else if(request is http.StreamedRequest) {
throw Exception('copying streamed requests is not supported');
}
else {
throw Exception('request type is unknown, cannot copy');
}
requestCopy
..persistentConnection = request.persistentConnection
..followRedirects = request.followRedirects
..maxRedirects = request.maxRedirects
..headers.addAll(request.headers);
return requestCopy;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2792 次 |
| 最近记录: |