Giter Site home page Giter Site logo

Comments (1)

wilinz avatar wilinz commented on August 14, 2024

My solution:

import 'package:dio/dio.dart';

typedef RedirectCallback = bool Function(
    Response response, ResponseInterceptorHandler handler);

class RedirectInterceptor extends Interceptor {
  final Dio _dio;
  RedirectCallback? _redirectCallback;
  static const String followRedirects = "followRedirects";
  static const String rawUri = "rawUri";
  static const String rawRequestOption = "rawRequestOption";
  static const String redirectCount = "redirectCount";

  RedirectInterceptor(this._dio, {RedirectCallback? onRedirect})
      : _redirectCallback = onRedirect;

  @override
  Future<void> onResponse(
      Response response, ResponseInterceptorHandler handler) async {
    final isFollowRedirects =
        response.requestOptions.extra[followRedirects] as bool? ?? true;
    if (!isFollowRedirects) {
      handler.next(response);
      return;
    }

    final rawUriValue = response.requestOptions.extra[rawUri] as Uri?;
    if (rawUriValue == null) {
      response.requestOptions.extra[rawUri] = response.requestOptions.uri;
    }
    final rawRequestOptionValue = response.requestOptions.extra[rawRequestOption];
    if (rawRequestOptionValue == null){
      response.requestOptions.extra[rawRequestOption] = response.requestOptions;
    }

    if (_isRedirect(response.statusCode ?? 0)) {
      try {
        final redirectCountValue =
            response.requestOptions.extra[redirectCount] ?? 0;
        if (redirectCountValue >= 5) {
          handler.next(response);
          return;
        }
        if (_redirectCallback != null &&
            !_redirectCallback!.call(response, handler)) {
          return;
        }
        final location = response.headers.value('location');
        if (location == null) throw Exception("Redirect location is null");
        final requestOptions = response.requestOptions;
        final rawUri = requestOptions.uri.toString();
        final newUri = Uri.parse(_parseHttpLocation(rawUri, location));
        response.requestOptions.extra[redirectCount] = redirectCountValue + 1;

        final option = Options(
          sendTimeout: requestOptions.sendTimeout,
          receiveTimeout: requestOptions.receiveTimeout,
          extra: requestOptions.extra,
          // headers: requestOptions.headers
          //   ..removeWhere((key, value) {
          //     return key.toLowerCase() == "cookie" || key.toLowerCase() == 'content-length';
          //   }),
          responseType: requestOptions.responseType,
          validateStatus: requestOptions.validateStatus,
          receiveDataWhenStatusError: requestOptions.receiveDataWhenStatusError,
          followRedirects: requestOptions.followRedirects,
          maxRedirects: requestOptions.maxRedirects,
          persistentConnection: requestOptions.persistentConnection,
          requestEncoder: requestOptions.requestEncoder,
          responseDecoder: requestOptions.responseDecoder,
          listFormat: requestOptions.listFormat,
        );

        final redirectResponse = await _dio.getUri(
          newUri,
          options: option,
        );
        return handler.next(redirectResponse);
      } on DioException catch (e) {
        return handler.reject(e);
      }
    }
    return handler.next(response);
  }

  bool _isRedirect(int statusCode) {
    return statusCode == 301 ||
        statusCode == 302 ||
        statusCode == 303 ||
        statusCode == 307 ||
        statusCode == 308;
  }

  String _parseHttpLocation(final String rawUri, final String location) {
    var location1 = location;
    String uri;
    if (!location1.contains("://")) {
      final schemaEndIndex = rawUri.indexOf("://") + 3;
      var index = location1.startsWith("/")
          ? rawUri.indexOf("/", schemaEndIndex)
          : rawUri.substring(schemaEndIndex).lastIndexOf("/") + schemaEndIndex;
      if (index == -1) index = rawUri.length - 1;
      var baseUrl = rawUri.substring(0, index + 1);
      if (baseUrl.endsWith("/")) {
        baseUrl = baseUrl.substring(0, baseUrl.length - 1);
      }
      if (location1.startsWith("/")) {
        location1 = location1.substring(1);
      }
      uri = baseUrl + "/" + location1;
    } else {
      uri = location1;
    }
    return uri;
  }
}

from dio.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.