Dart Web Request and Response as a Stream of data - dart

I have been trying to setup an HTTP connection from a Dart client to a Dart Server using the HttpServer and HttpClient classes respectively.
I want to use this connection to transmit event updates to the client whenever the server feels necessary, so the connection needs to be continuous and the response needs to be sent in chunks, not buffered.
I tried this approach using two different server configurations (once with HttpServer, once with Shelf), but both times the response awaited closing and then the data was printed by the client.
Here is my server code:
var httpsServer = await io.HttpServer.bind("127.0.0.1", 4001);
httpsServer.listen((request) {
request.response.bufferOutput = false;
request.response.headers.add("Content-Type", "text/event-stream");
request.response.headers.add("Cache-Control", "no-cache");
request.response.headers.add("Connection", "keep-alive");
// asynchronously write "Hello" every 100 ms
Timer.periodic(Duration(milliseconds: 100), (Timer timer) {
try {
request.response.write("Hello\n");
} catch (_) {
timer.cancel();
}
});
await Future.delayed(Duration(seconds: 3));
request.response.close();
});
And another using shelf:
{
var handler = const Pipeline().addMiddleware(logRequests()).addHandler(_echoRequest);
var server = await serve(handler, '127.0.0.1', 4000);
server.autoCompress = true;
}
FutureOr<Response> _echoRequest(Request request) {
Stream<List<int>> stream = Stream.periodic(Duration(milliseconds: 100), (int i) {
return utf8.encode("Hello\n");
}).take(10);
return Response.ok(stream);
}
However, on the client, I only receive the data once the connection has been closed:
HttpClient client = HttpClient()..badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
HttpClientRequest request = await client.postUrl(Uri.parse('https://---/'));
request.headers.add('Content-Type', 'text/event-stream');
HttpClientResponse response = await request.close();
// use startChunkConversion to convert the stream of bytes to a stream of strings
Stream<String> stream = response.transform(utf8.decoder).transform(const LineSplitter());
await for (String line in stream) {
print(line);
}
Am I doing something wrong or would I be better off with a different library / approach?

Related

flutter socket.io client not working ~~~ helpme

I am making a chat app using flutter.
However, the socket connection does not work.
Port 80 is all connected locally, but sockets using aws are not connected.
I've tried both http and https, but no response. Help me!
Only the app does not connect, but the web connects.
The version of socket io client is 1.0.2, and the version of socket io is 2.3.0.
class _WebrtcState extends State<Webrtc> {
late final IO.Socket socket;
// late final SocketIO socketIO;
final _localRenderer = RTCVideoRenderer();
final _remoteRenderer = RTCVideoRenderer();
MediaStream? _localStream;
RTCPeerConnection? pc;
String check = "aafafasdfs";
#override
void initState() {
print('initState');
init();
super.initState();
}
Future init() async {
print('init');
await _localRenderer.initialize();
await _remoteRenderer.initialize();
await connectSocket();
await joinRoom();
}
Future connectSocket() async {
print('connectSocket');
socket = IO.io('http://********', IO.OptionBuilder().setTransports(['websocket']).build());
print(socket.opts);
socket.onConnect( (_){
print('connect');
setState(() {
check = "11111111111111111111ㅈ111";
});
});
socket.on('joined', (data) {
_sendOffer();
});
socket.on('offer', (data) async{
data = jsonDecode(data);
await _getOffer(RTCSessionDescription(data['sdp'], data['type']));
await _sendAnswer();
});
socket.on('answer', (data) {
data = jsonDecode(data);
_getAnswer(RTCSessionDescription(data['sdp'], data['type']));
});
socket.on('ice', (data) {
data = jsonDecode(data);
_getIce(RTCIceCandidate(data['candidate'], data['sdpMid'], data['sdpMLineIndex']));
});
}
}
To open a WebSocket connection, we need to create a new WebSocket using the special protocol ws in the URL:
final channel = WebSocketChannel.connect(
Uri.parse('wss://echo.websocket.org'),
);
There's also encrypted wss:// protocol. It's like HTTPS for WebSockets.
Please change the URL to something like the below form :
ws://********
wss://********

How to read file from HTTPRequest on a dart:io server

I am trying to create a server to run locally for my application to upload some files while debugging. It is very simple and the full source code is:
import 'dart:io';
void main(List<String> arguments) async {
const port = 8080;
final server = await HttpServer.bind(InternetAddress.anyIPv4, port);
server.listen((request) async {
if (request.uri.path != '/save_screenshot' || request.method != 'POST') {
request.response.statusCode = 404;
request.response.close();
return;
}
// TODO: read the file
request.response.statusCode = 200;
request.response.close();
});
print('screenshot server listening on $port.');
}
At the code there is a TODO comment, where I would like to read the file from the HTTPRequest, I googled a bit and could not find a example to copy. Does anyone know how to read the file from the HTTPRequest?
Here is how it is being sent (on the client side):
final url = 'http://<local_ip_address>:8080/save_screenshot';
var request = http.MultipartRequest('POST', Uri.parse(url));
request.files.add(
http.MultipartFile.fromBytes(
'file',
screenshot.bytes,
filename: 'screenshot.png',
),
);
await request.send();
I found out how to read the file from the HTTPRequest. But for it to work it is necessary to install a package called mime.
Then replace the TODO comment in the question with:
final boundary = request.headers.contentType!.parameters['boundary']!;
final mimeTransformer = MimeMultipartTransformer(boundary);
final parts = request.cast<List<int>>().transform(mimeTransformer);
await for (final part in parts) {
final file = File('uploaded_files/0.png');
await part.pipe(file.openWrite());
}
I made a gist with the working server: https://gist.github.com/lslv1243/1036364b10c6578d969cb4ed2d7eba42
NOTE: on the gist I changed the path from /save_screenshot to /screenshot

Riverpod StreamProvider access the stream

I am using socket_client_io and Riverpod. Socket client uses events for updates which I want to propagate in a StreamProvider.
What I currently have is the following. It gets the job done but... I would like to write directly to the stream within StreamProvider so I don't need to create an extra stream just to go from events to yield.
final downloadProgressProvider = StreamProvider.autoDispose<Progress>((ref) async* {
// open socketio
final Server host = ref.read(configProvider).talkServer;
final String jwt = ref.read(userProvider).jwt;
IO.Socket _socket = IO.io('${host.uri.toString()}/?token=$jwt', IO.OptionBuilder()
.setTransports(['websocket'])
.build()
);
StreamController<Progress> _stream = StreamController<Progress>();
ref.onDispose(() {
// close socketio
_stream.close();
_stream = null;
_socket.dispose();
_socket = null;
});
_socket.on('download-update', (message) {
print('download-update incoming');
_stream.add(Progress.fromJson(json.decode(message)))
});
await for (final value in _stream.stream) {
yield value;
}
});

Is there any same method in swift to read InpuStream using post http request

Is there any same method present in swift to read the input stream from HTTP request
InputStream in = address.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder result = new StringBuilder();
String line;
while((line = reader.readLine()) != null) {
result.append(line);
}
System.out.println(result.toString());
This is a local server is sending two response with 207:
var http = require('http');
var express = require('express')();
var port = process.env.PORT || 3000;
var promise = new Promise(function(resolve, reject) {
const x = "geeksforgeeks";
const y = "geeksforgeeks"
if(x === y) {
console.log('resolve');
resolve();
} else {
reject();
}
});
express.post('/', function(req, res) {
console.log('send req1')
// check if network exists and user requesting is owner of it
return promise.then(() => {
// add listener to receive response from gateway and forward it
//_addGwEmitter.addGwEmitter.addEventListener(req, res, gatewayPsn);
// send the gateway trigger instructions to coco user
res.status(207).write(JSON.stringify({
status: 200,
msg: "Waiting for authorization\n",
instructionText: "devProductInfo.instructionText",
instructionImage: "devProductInfo.instructionImageURL"
}) + "\n \r End" );
// if no event is received from gateway trigger timeout after 60 seconds
res.setTimeout(6000,()=>{
console.log('send req 2');
res.status(207).write(JSON.stringify({
status: 200,
msg: "authorization done \n",
instructionText: "devProductInfo.instructionText",
instructionImage: "devProductInfo.instructionImageURL"
}));
res.end();
});
}).catch(error => {
return res.status(400).send("error.getErrorInfo()");
});
});
http.createServer(express).listen(port);
i want to read two response one by one
i have tried
uploadtask
downloadTask
dataTask
in HTTP URLSession.
I got the answer if you want to use 207 response in iOS devices then implement URL data Task with delegate and in data delegate, you will get the response data. make sure response content type is text/json

Failed to upload image to twitter using RestSharp

I'm trying to upload image in WinRT application to twitter using RestSharp
Code is here:
RestClient twClient = new RestClient("https://upload.twitter.com");
twClient.Authenticator = OAuth1Authenticator.ForProtectedResource(........);
var postTweet = new RestRequest("/1/statuses/update_with_media.json", Method.POST);
postTweet.AddParameter("status", TweetBox.Text);
byte[] img = await GetDataAsync(imageFile);
postTweet.AddFile("media[]", img, imageFile.Name, "multipart/form-data");
twClient.ExecuteAsync(postTweet, (response =>
{
try
{
if (response.StatusCode == HttpStatusCode.OK)
{
....
Here is my GetDataAsync, which takes byte array from file in Isolated Storage
public static async Task<byte[]> GetDataAsync(StorageFile file)
{
IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
DataReader reader = new DataReader(stream.GetInputStreamAt(0));
uint streamSize = (uint)stream.Size;
await reader.LoadAsync(streamSize);
byte[] buffer = new byte[streamSize];
reader.ReadBytes(buffer);
return buffer;
}
Server response:
Expectation Failed
The expectation given in the Expect request-header field could not be met by this server.
The client sent
Expect: 100-continue
but we only allow the 100-continue expectation.

Resources