Трепетание http StreamedResponse.stream и StreamedResponse.sink

#flutter #http #flutter-http

#трепетание #http #трепетание-http

Вопрос:

Я изучаю третий пример http-пакета Flutter, это основа кода: https://pub.dev/packages/http

Когда запрос отправляется через BaseClient.send, немедленно будут отправлены только заголовки и все данные, которые уже были записаны в StreamedRequest.stream. Дополнительные данные будут отправлены, как только они будут записаны в StreamedRequest.sink, и когда приемник будет закрыт, запрос завершится.

https://pub.dev/documentation/http/latest/http/StreamedRequest-class.html

  1. Из документов я не понимаю, как мы должны писать StreamedRequest.stream ? (Для немедленной отправки данных)

  2. Не является StreamedResponse .sink в основном там, где мы добавляем тело запроса нашего HTTP POST: почему он принимает только a List<int> ? Разве это не должно быть a Map<String, String> ? Если это не так, то куда мы должны добавить тело запроса? NEW: Даже когда я кодирую его с помощью ut8.encode, он по-прежнему не отображается в веб-формах Fiddler при отладке, как мне правильно отправить x-www-form-urlencoded?:

Код:

 userAgentClient = UserAgentClient(userAgent, client);
streamedRequest = http.StreamedRequest('POST', Uri(scheme: 'http', path: '/posts/', host: 'jsonplaceholder.typicode.com'));
streamedRequest.sink.add([123, 456]); // It has to be a List<int>

//NEW:
streamedRequest.sink.add(utf8.encode('username=123amp;password=456'));
streamedRequest.sink.add(utf8.encode('{"username":"123","password":"456"}'));
  
  1. Почему я должен закрывать приемник, чтобы иметь доступ к свойствам StreamedResponse?

streamedRequest.sink.close();

Обновить:

 class UserAgentClient extends http.BaseClient {
  final String userAgent;
  final http.Client client;
  UserAgentClient(this.userAgent, this.client);
  Future<http.StreamedResponse> send(http.BaseRequest request){
    request.headers['user-agent'] = userAgent;
    return client.send(request);
  }
}

dynamic _status = '';
dynamic _body = '';
dynamic _headers = '';
String _reason = '';
http.Client client = http.Client();
String userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36';
UserAgentClient userAgentClient;
http.StreamedRequest streamedRequest;

void _httpStreamed(){
  userAgentClient = UserAgentClient(userAgent, client);
  streamedRequest = http.StreamedRequest('POST', Uri(scheme: 'http', path: '/posts/', host: 'jsonplaceholder.typicode.com'));
  streamedRequest.sink.add(utf8.encode('{"username":"123","password":"456"}'));
  setState(() {
    _status = streamedRequest.url;
    _body = '';
    _headers = '';
    _reason = '';
  });
}

void _httpSend() async{
    http.StreamedResponse streamedResponse;
    streamedResponse = await userAgentClient.send(streamedRequest);
    streamedResponse.stream.listen(
      (value) async{
          _body = http.ByteStream.fromBytes(value);
          _body = await _body.bytesToString();
      },
      onError: (e, sT) {
        SnackBar sBar = SnackBar(content: Text('$en$sT',));
        Scaffold.of(context).showSnackBar(sBar);
      },
      onDone: () {
        SnackBar sBar = SnackBar(content: Text('Done lol'),);
        Scaffold.of(context).showSnackBar(sBar);
      },
    );
    setState(() {
      _body;
      _status = streamedResponse.statusCode;
      _headers = streamedResponse.headers;
      _reason = streamedResponse.reasonPhrase;
    });
  }
}

void _httpClose(){
  if (streamedRequest != null){
    streamedRequest.sink.close();
  }
}
  

Итак, я запускаю первые 2 функции, но _body переменная не отображается на моем экране, пока я не запущу _httpClose() функцию.

Комментарии:

1. этот обновленный код, который вы создали, является полностью рабочей версией?

2. @CassioSeffrin Я изучаю Flutter, и я пытался полностью изучить пакет http Flutter, поэтому я создал приложение для тестирования всего, что в нем есть. Поскольку вы заинтересованы, я загрузил полностью рабочую версию здесь для вас: github.com/Saya47/Flutter-http-learning Весь код находится в одном файле dart, скопируйте и вставьте его в свой тестовый проект flutter, создайте приложение и протестируйте все!

3. Спасибо @Shayan. На данный момент мне нужно только проверить, сработал ли этот потоковый запрос. Я сделал это по-другому: окончательный запрос = запрос (‘GET’, Uri.parse(url)); request.headers.addAll(заголовки); окончательный ответ StreamedResponse = ожидание клиента ().отправить (запрос); Дополнительно мне нужно настроить тайм-аут, но Client().у отправки нет аргументов, необходимых для этого.

Ответ №1:

  1. ДА

  2. Map<String,String> не может быть потоковым. Потоковое означает, что данные отправляются порциями каждый раз, когда поток отправляет порцию данных, и сервер (или буфер отправки браузеров) готов к приему дополнительных данных. List<int> может быть разделен на фрагменты, потому что не имеет значения, сколько байтов отправляется одновременно. Если у вас есть все доступные данные, вы, вероятно, не хотите использовать StreamedRequest, особенно если это не большой двоичный объект данных. https://en.wikipedia.org/wiki/Binary_large_object

utf8.encode может использоваться для кодирования фрагментов, передаваемых потоком, но сам по себе поток не создается, поэтому вы не можете добавить результат utf8.encode в приемник.

  1. Я не понимаю этого вопроса. К каким свойствам doe вы хотите получить доступ и с какими проблемами вы сталкиваетесь при попытке?

Для меня не похоже, что вам не нужно использовать StreamedRequest для вашего варианта использования.

Комментарии:

1. Большое спасибо, теперь все имеет смысл, для 3, в основном, когда я хочу проверить ответ сервера, например, тело, оно не отображается, пока я не закрою приемник, я обновлю свой код через минуту.

2. Хорошо, это невозможно, потому что запрос не может быть завершен до закрытия потока (сигнализируется, что больше не будет данных), и вы не можете получить доступ к ответу до запроса, очевидно;-)