From c090cae1a1d7e3236997e1bd1f5c557f27a5fee1 Mon Sep 17 00:00:00 2001 From: My-Responsitories <107370289+My-Responsitories@users.noreply.github.com> Date: Thu, 1 May 2025 10:08:48 +0800 Subject: [PATCH] opt: post redirect (#788) * opt: cookie * opt: post redirect --- lib/http/init.dart | 22 +----- lib/http/live.dart | 4 +- lib/http/retry_interceptor.dart | 68 +++++++++++++------ .../video/detail/post_panel/post_panel.dart | 28 ++++---- .../accounts/account_manager/account_mgr.dart | 13 +--- 5 files changed, 68 insertions(+), 67 deletions(-) diff --git a/lib/http/init.dart b/lib/http/init.dart index d31b7b39..d656526f 100644 --- a/lib/http/init.dart +++ b/lib/http/init.dart @@ -164,10 +164,8 @@ class Request { : http11Adapter; // 先于其他Interceptor - if (GStorage.retryCount > 0) { - dio.interceptors - .add(RetryInterceptor(GStorage.retryCount, GStorage.retryDelay)); - } + dio.interceptors + .add(RetryInterceptor(GStorage.retryCount, GStorage.retryDelay)); // 日志拦截器 输出请求、响应内容 if (BuildConfig.isDebug) { @@ -222,7 +220,7 @@ class Request { * post请求 */ Future post(url, - {data, queryParameters, options, cancelToken, isRedirect}) async { + {data, queryParameters, options, cancelToken}) async { // debugPrint('post-data: $data'); Response response; try { @@ -236,20 +234,6 @@ class Request { // debugPrint('post success: ${response.data}'); return response; } on DioException catch (e) { - if (isRedirect != true && - const [301, 302, 303, 307, 308].contains(e.response?.statusCode)) { - String? redirectUrl = e.response?.headers['location']?.firstOrNull; - if (redirectUrl != null) { - return await post( - redirectUrl, - data: data, - queryParameters: queryParameters, - options: options, - cancelToken: cancelToken, - isRedirect: true, - ); - } - } AccountManager.toast(e); Response errResponse = Response( data: { diff --git a/lib/http/live.dart b/lib/http/live.dart index 6a549e51..8d3f82c0 100644 --- a/lib/http/live.dart +++ b/lib/http/live.dart @@ -35,10 +35,8 @@ class LiveHttp { 'origin': 'https://live.bilibili.com', 'referer': 'https://live.bilibili.com/', 'user-agent': Request.headerUa(type: 'pc'), + if (gaiaVtoken == null) 'cookie': 'x-bili-gaia-vtoken=$gaiaVtoken' }, - extra: gaiaVtoken == null - ? null - : {'cookie': 'x-bili-gaia-vtoken=$gaiaVtoken'}, ), ); if (res.data['code'] == 0) { diff --git a/lib/http/retry_interceptor.dart b/lib/http/retry_interceptor.dart index 6e4647a7..1aa2385e 100644 --- a/lib/http/retry_interceptor.dart +++ b/lib/http/retry_interceptor.dart @@ -10,26 +10,56 @@ class RetryInterceptor extends Interceptor { @override void onError(DioException err, ErrorInterceptorHandler handler) { - if (err.response != null) return handler.next(err); - switch (err.type) { - case DioExceptionType.connectionError: - case DioExceptionType.connectionTimeout: - case DioExceptionType.sendTimeout: - case DioExceptionType.unknown: - if ((err.requestOptions.extra['_rt'] ??= 0) < _count) { - Future.delayed( - Duration( - milliseconds: ++err.requestOptions.extra['_rt'] * _delay), - () => Request.dio - .fetch(err.requestOptions) - .then(handler.resolve) - .onError((error, _) => handler.reject(error))); - } else { - handler.next(err); + if (err.response != null) { + final options = err.requestOptions; + if (options.followRedirects && options.maxRedirects > 0) { + final status = err.response!.statusCode; + if (status != null && 300 <= status && status < 400) { + var redirectUrl = err.response!.headers.value('location'); + if (redirectUrl != null) { + var uri = Uri.parse(redirectUrl); + if (!uri.hasScheme) { + uri = options.uri.resolveUri(uri); + redirectUrl = uri.toString(); + } + (options..path = redirectUrl).maxRedirects--; + if (status == 303) { + options.data = null; + options.method = 'GET'; + } + Request.dio + .fetch(options) + .then((i) => handler.resolve(i + ..redirects.add(RedirectRecord(status, options.method, uri)) + ..isRedirect = true)) + .onError((error, _) => handler.next(error)); + return; + } } - return; - default: - return handler.next(err); + } + return handler.next(err); + } else { + switch (err.type) { + case DioExceptionType.connectionError: + case DioExceptionType.connectionTimeout: + case DioExceptionType.sendTimeout: + case DioExceptionType.unknown: + if ((err.requestOptions.extra['_rt'] ??= 0) < _count) { + Future.delayed( + Duration( + milliseconds: ++err.requestOptions.extra['_rt'] * _delay), + () => Request.dio + .fetch(err.requestOptions) + .then(handler.resolve) + .onError( + (error, _) => handler.reject(error))); + } else { + handler.next(err); + } + return; + default: + return handler.next(err); + } } } } diff --git a/lib/pages/video/detail/post_panel/post_panel.dart b/lib/pages/video/detail/post_panel/post_panel.dart index 57d18ba5..8cf25264 100644 --- a/lib/pages/video/detail/post_panel/post_panel.dart +++ b/lib/pages/video/detail/post_panel/post_panel.dart @@ -535,8 +535,8 @@ class _PostPanelState extends CommonCollapseSlidePageState { ]; } - void _onPost({String? url}) async { - Request().post( + Future _onPost({String? url}) { + return Request().post( url ?? '${GStorage.blockServer}/api/skipSegments', data: { 'videoID': videoDetailController.bvid, @@ -557,14 +557,9 @@ class _PostPanelState extends CommonCollapseSlidePageState { ) .toList(), }, - options: Options( - validateStatus: (int? status) { - return status != null && - ((status >= 200 && status < 300) || - const [400, 403, 429, 409].contains(status)); - }, - ), - ).then( + options: Options(followRedirects: true), + ) + .then( (res) { if (res.statusCode == 200) { Get.back(); @@ -578,12 +573,13 @@ class _PostPanelState extends CommonCollapseSlidePageState { } } else { SmartDialog.showToast( - '提交失败: ${const { - 400: '参数错误', - 403: '被自动审核机制拒绝', - 429: '重复提交太快', - 409: '重复提交' - }[res.statusCode] ?? res.statusCode}', + '提交失败: ${switch (res.statusCode) { + 400 => '参数错误', + 403 => '被自动审核机制拒绝', + 429 => '重复提交太快', + 409 => '重复提交', + _ => res.statusCode.toString() + }}', ); } }, diff --git a/lib/utils/accounts/account_manager/account_mgr.dart b/lib/utils/accounts/account_manager/account_mgr.dart index 7889cfbf..25891139 100644 --- a/lib/utils/accounts/account_manager/account_mgr.dart +++ b/lib/utils/accounts/account_manager/account_mgr.dart @@ -129,20 +129,13 @@ class AccountManager extends Interceptor { account.cookieJar.loadForRequest(options.uri).then((cookies) { final previousCookies = options.headers[HttpHeaders.cookieHeader] as String?; - String newCookies = getCookies([ + final newCookies = getCookies([ ...?previousCookies ?.split(';') .where((e) => e.isNotEmpty) .map((c) => Cookie.fromSetCookieValue(c)), ...cookies, ]); - if (options.extra['cookie'] != null) { - if (newCookies.isEmpty) { - newCookies = '${options.extra['cookie']}'; - } else { - newCookies += ';${options.extra['cookie']}'; - } - } options.headers[HttpHeaders.cookieHeader] = newCookies.isNotEmpty ? newCookies : ''; handler.next(options); @@ -177,7 +170,7 @@ class AccountManager extends Interceptor { } @override - void onError(DioException err, ErrorInterceptorHandler handler) async { + void onError(DioException err, ErrorInterceptorHandler handler) { if (err.requestOptions.method != 'POST') { toast(err); } @@ -198,7 +191,7 @@ class AccountManager extends Interceptor { } } - static void toast(err) { + static void toast(DioException err) { const List skipShow = [ 'heartbeat', 'history/report',