Flutter chopper swagger_dart_code_generator API无响应地无休止地重复请求

huangapple go评论72阅读模式
英文:

Flutter chopper swagger_dart_code_generator API repeating request endlessly without response

问题

I am trying to set up a client to my nestJs server. I generate a swagger documentation with nestJS/swagger and from there I use the swagger_dart_code_generator to generate the API code for my client. The Server works fine, I tested this with Postman. All request do as they should.

The problem is my client. When I call any generated API function it goes to the server as planned, the server builds its response and sends it back. BUT THEN my client function does not get the response and instead the request is sent to the server again in an endless loop. My original function never gets a response and just waits forever. I tested the behavior in windows, web, and android. I never get an error or an exception. Is there a configuration I am missing? What else could trigger this behavior?

Edit deleted since unrelated.

Here is the code I wrote:

//build.yaml

targets:
  $default:
    sources:
      - "lib/**"
      - "lib/swagger/**"
    builders:
      chopper_generator:
        options:
          header: "//Generated code"
      swagger_dart_code_generator:
        options:
          input_folder: "lib/swagger/"
          output_folder: "lib/swagger/models/"
          ignore_headers: true
          separate_models: true
//services.dart

import 'dart:async';
import 'package:get_it/get_it.dart';
import 'package:my_client/core/services/my_authenticator.dart';
import 'package:my_client/swagger/models/client_index.dart';

final getIt = GetIt.instance;

Future<void> setupServices() async {
  getIt.registerSingleton<MyApi>(MyApi.create(
    baseUrl: Uri.parse("http://localhost:3000"),
    authenticator: getIt<MyAuthenticator>(),
  ));
}
//my_authenticator.dart

import 'dart:async';
import 'dart:io';
import 'package:chopper/chopper.dart';

class MyAuthenticator extends Authenticator {
  String token = "";

  @override
  FutureOr<Request?> authenticate(
      Request request,
      Response response, [
        Request? originalRequest,
      ]) async {
    if (response.statusCode == HttpStatus.unauthorized) {
      final String? newToken = await refreshToken();

      if (newToken != null) {
        return request.copyWith(headers: {
          ...request.headers,
          HttpHeaders.authorizationHeader: newToken,
        });
      }
    }
    return request;
  }

  Future<String?> refreshToken() async {
    return token;
  }
}
//user_provider.dart

import 'package:my_client/core/extensions/date_time_extension.dart';
import 'package:my_client/core/models/user_week.dart';
import 'package:my_client/swagger/models/my_api.swagger.dart';

class UserWeekProvider {
  final MyApi _api;

  UserWeekProvider(this._api);

  Future<UserWeek?> getWorkWeek(DateTime? date) async {
    final dateString = (date ?? DateTime.now()).toIso8601String();

    final response = await _api.userWeekGet(
      date: dateString,
    );
    if (response.body == null) return null;
    return UserWeek.fromResponse(response.body!);
  }
}

(Note: I've fixed the HTML entity encoding in the code snippets for better readability.)

英文:

I am trying to set up a client to my nestJs server. I generate a swagger documentation with nestJS/swagger and from there I use the swagger_dart_code_generator to generate the API code for my client. The Server works fine, I tested this with Postman. All request do as they should.

The problem is my client. When I call any generated API function it goes to the server as planned, the server builds its response and sends it back. BUT THEN my client function does not get the response and instead the request is sent to the server again in an endless loop. My original function never gets a response and just waits forever. I tested the behavior in windows, web and android. I never get an error, or an exception. Is there a configuration I am missing? What else could trigger this behavior?

Edit deleted since unrelated.

Here is the code I wrote:

//build.yaml

targets:
  $default:
    sources:
      - &quot;lib/**&quot;
      - &quot;lib/swagger/**&quot;
    builders:
      chopper_generator:
        options:
          header: &quot;//Generated code&quot;
      swagger_dart_code_generator:
        options:
          input_folder: &quot;lib/swagger/&quot;
          output_folder: &quot;lib/swagger/models/&quot;
          ignore_headers: true
          separate_models: true
//services.dart

import &#39;dart:async&#39;;
import &#39;package:get_it/get_it.dart&#39;;
import &#39;package:my_client/core/services/my_authenticator.dart&#39;;
import &#39;package:my_client/swagger/models/client_index.dart&#39;;


final getIt = GetIt.instance;

Future&lt;void&gt; setupServices() async {
  getIt.registerSingleton&lt;MyApi&gt;(MyApi.create(
    baseUrl: Uri.parse(&quot;http://localhost:3000&quot;),
    authenticator: getIt&lt;MyAuthenticator&gt;(),
  ));
}
//my_authenticator.dart

import &#39;dart:async&#39;;
import &#39;dart:io&#39;;
import &#39;package:chopper/chopper.dart&#39;;

class MyAuthenticator extends Authenticator{

  String token = &quot;&quot;;

  @override
  FutureOr&lt;Request?&gt; authenticate(
      Request request,
      Response response, [
        Request? originalRequest,
      ]) async {
    if (response.statusCode == HttpStatus.unauthorized) {
      final String? newToken = await refreshToken();

      if (newToken != null) {
        return request.copyWith(headers: {
          ...request.headers,
          HttpHeaders.authorizationHeader: newToken,

        });
      }
    }
    return request;
  }

  Future&lt;String?&gt; refreshToken() async {
    return token;
  }

}
//user_provoider.dart

import &#39;package:my_client/core/extensions/date_time_extension.dart&#39;;
import &#39;package:my_client/core/models/user_week.dart&#39;;
import &#39;package:my_client/swagger/models/my_api.swagger.dart&#39;;

class UserWeekProvider {
  final MyApi _api;

  UserWeekProvider(this._api);

  Future&lt;UserWeek?&gt; getWorkWeek(DateTime? date) async {
    final date = (date?? DateTime.now()).toIso8601String();

    final response = await _api.userWeekGet(
        date: date
    );
    if (response.body == null) return null;
    return UserWeek.fromResponse(response.body!);
  }
}

答案1

得分: 0

我找到了。它是Authenticator。旧的版本总是返回一个请求,所以chopper会在无限循环中再次尝试。现在,除了未经授权的情况外,我会始终返回null。因此,它不会再次尝试。实际的身份验证过程尚未实施。但现在它可以正常工作。

这个更改现在有效:

class MyAuthenticator extends Authenticator {
  String token = "";

  @override
  FutureOr<Request?> authenticate(
    Request request,
    Response response, [
    Request? originalRequest,
  ]) async {
    if (response.statusCode == HttpStatus.unauthorized) {
      String? newToken = await refreshToken();

      final Map<String, String> updatedHeaders =
          Map<String, String>.of(request.headers);

      if (newToken != null) {
        newToken = 'Bearer $newToken';
        updatedHeaders.update('Authorization', (String _) => newToken!,
            ifAbsent: () => newToken!);
        return request.copyWith(headers: updatedHeaders);
      }
    }
    return null;
  }

  Future<String?> refreshToken() async {
    return token;
  }
}
英文:

I found it. It is the Authenticator. The old one always returned a request, and so chopper tried again in an endless loop. Now I give back a null in any case other than an unauthorized. So it does not try again. The actually authenticate process is not implemented. But it works for now.

This change works now:

class MyAuthenticator extends Authenticator {
  String token = &quot;&quot;;

  @override
  FutureOr&lt;Request?&gt; authenticate(
    Request request,
    Response response, [
    Request? originalRequest,
  ]) async {
    if (response.statusCode == HttpStatus.unauthorized) {
      String? newToken = await refreshToken();

      final Map&lt;String, String&gt; updatedHeaders =
          Map&lt;String, String&gt;.of(request.headers);

      if (newToken != null) {
        newToken = &#39;Bearer $newToken&#39;;
        updatedHeaders.update(&#39;Authorization&#39;, (String _) =&gt; newToken!,
            ifAbsent: () =&gt; newToken!);
        return request.copyWith(headers: updatedHeaders);
      }
    }
    return null;
  }

  Future&lt;String?&gt; refreshToken() async {
    return token;
  }
}

huangapple
  • 本文由 发表于 2023年7月18日 15:35:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76710461.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定