CodingAleCR / http_interceptor

A lightweight, simple plugin that allows you to intercept request and response objects and modify them if desired.
MIT License
133 stars 67 forks source link

Adding onError() method to the interceptor #14

Closed kwado-tech closed 4 years ago

kwado-tech commented 4 years ago

Thanks for this awesome package. My use case involves re-authorization using refreshToken and this can be done if an error-code is intercepted and a new token request. This feature would be greatly appreciated. Thanks

issue-label-bot[bot] commented 4 years ago

Issue-Label Bot is automatically applying the label feature_request to this issue, with a confidence of 0.94. Please mark this comment with :thumbsup: or :thumbsdown: to give our bot feedback!

Links: app homepage, dashboard and code for this bot.

CodingAleCR commented 4 years ago

Hey, this sounds like an awesome idea, I will add it to the work I've got pending. Thank you very much 🙌🏼

kwado-tech commented 4 years ago

That's great can wait for the feature

On Wed, Jan 15, 2020, 3:22 PM Alejandro Ulate notifications@github.com wrote:

Hey, this sounds like an awesome idea, I will add it to the work I've got pending. Thank you very much 🙌🏼

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/CodingAleCR/http_interceptor/issues/14?email_source=notifications&email_token=ALNHCQXF3DM2V3URLUUIGCLQ54SZPA5CNFSM4KGL2IOKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJAVXTA#issuecomment-574708684, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALNHCQSGULJEC6W4URCFJ7LQ54SZPANCNFSM4KGL2IOA .

CodingAleCR commented 4 years ago

Hey, I was thinking about this a bit longer and well.. you can currently use this through an interceptor, maybe you can share some of your code so I can help to guide you in the right direction.

alienriquebm commented 4 years ago

Hi my friend. I see it this question and i think i can ask here my own...

I have this code trying to intercept any error on the responses, but doesn't work. Can you help me @CodingAleCR ? Thanks!

import 'dart:convert';

import 'package:flutter/material.dart';

import '../models/http_exception.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http_interceptor/http_interceptor.dart';

class ApiInterceptor with ChangeNotifier implements InterceptorContract  {
  final storage = new FlutterSecureStorage();
  @override
  Future<RequestData> interceptRequest({RequestData data}) async {
    try {
      data.headers["Content-Type"] = "application/json";
      String token = await storage.read(key: 'token');
      if (token != null) {
        data.headers["Authorization"] = "Bearer $token";
      }
    } catch (e) {
      print(e);
    }
    return data;
  }

  @override
  Future<ResponseData> interceptResponse({ResponseData data}) async {
    print('DATA HEREEEEEEEEEEEEEEEEEEEEEe');
    print(data);
    try {
      final decodedResponse = json.decode(data.body);
      if (data.statusCode >= 400) {
        throw HttpException(decodedResponse['error']);
      }
    } catch (error) {
      if (error.toString().contains('Connection refused')) {
        throw HttpException(
            'Error de conexión al servidor, por favor reintente más tarde.');
      }
    }

    return data;
  }
}
CodingAleCR commented 4 years ago

Hi, I will try to get a look in detail, are you sure the API you are doing requests to is returning with a status code of 400 or more, and then if it does, are you getting any information on it or is the project crashing? Also, You might want to add limitations so that the status code is between 400 and 499 since 500+ is used for Server errors.

CodingAleCR commented 4 years ago

Hi, I was able to take a quick look to this today, so here's what is happening.

Request/Response Flow:

  1. You send a request to a server.
  2. Server responds with a status code >= 400.
  3. Your interceptor takes it, and it throws the exception you created.
  4. The plugin transmits the exception to the next in line listening. This means that you should have a try-catch block when you are using the HttpClientWithInterceptor or the HttpWithInterceptor.

For example, here's how it would look in the library's example:

class WeatherApiInterceptor implements InterceptorContract {
  @override
  Future<RequestData> interceptRequest({RequestData data}) async {
    try {
      data.params['appid'] = OPEN_WEATHER_API_KEY;
      data.params['units'] = 'metric';
      data.headers["Content-Type"] = "application/json";
    } catch (e) {
      print(e);
    }
    return data;
  }

  @override
  Future<ResponseData> interceptResponse({ResponseData data}) async {
    try {
      final decodedResponse = json.decode(data.body);
      if (data.statusCode >= 400) {
        throw Exception("Error while fetching: ${decodedResponse['error']}");
      }
    } catch (error) {
      if (error.toString().contains('Connection refused')) {
        throw Exception("Error while fetching: ${error.toString()}");
      }
    }

    return data;
  }
}

class WeatherRepository {
  HttpClientWithInterceptor client;

  WeatherRepository(this.client);

  Future<Map<String, dynamic>> fetchCityWeather(int id) async {
    var parsedWeather;
    try {
      final response =
          await client.get("$baseUrl/weather", params: {'id': "$id"});
      if (response.statusCode == 200) {
        parsedWeather = json.decode(response.body);
      } else {
        print("Error: ${response.body}");
        return Future.error(
          "Error while fetching.",
          StackTrace.fromString("${response.body}"),
        );
      }
    } catch (e) {
      print(e);
    }
    return parsedWeather;
  }
}