I'm learning the third example of Flutter http package, this is the base of the code: https://pub.dev/packages/http
When the request is sent via BaseClient.send, only the headers and whatever data has already been written to StreamedRequest.stream will be sent immediately. More data will be sent as soon as it's written to StreamedRequest.sink, and when the sink is closed the request will end.
https://pub.dev/documentation/http/latest/http/StreamedRequest-class.html
From the docs, I don't understand how we should write to
StreamedRequest.stream
? (To send data immediately)Isn't StreamedResponse.sink basically where we add our HTTP POST's Request Body: Why does it only accept a
List<int>
? Shouldn't it be aMap<String, String>
? If it's not then where should we add the request body?NEW:
Even when I encode it with ut8.encode, it still doesn't show up on Fiddler's WebForms when I'm debugging, how do I send a x-www-form-urlencoded properly?:
Code:
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=123&password=456'));
streamedRequest.sink.add(utf8.encode('{"username":"123","password":"456"}'));
- Why do I have to close the sink to be able to access StreamedResponse's properties?
streamedRequest.sink.close();
Update:
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('$e\n$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();
}
}
So I run the first 2 functions but the _body
variable doesn't show up on my screen until I run the _httpClose()
function.
yes
Map<String,String>
can not be streamed. Streamed means the data is sent in chunks every time a chunk of data is emitted by the stream and the server (or the browsers send buffer) is ready to receive more data.List<int>
can be chunked because it doesn't matter how many bytes are sent at once. If you have all data readily available, you probably do not want to use a StreamedRequest, expecially if it is not a blob of data. https://en.wikipedia.org/wiki/Binary_large_objectutf8.encode
can be used to encode chunks emitted by a stream, but it doesn't provide a stream by itself, so you can't add the result ofutf8.encode
to a sink.To me it doesn't look like you don't need to use StreamedRequest for your use case.