I have created a server using a Plane dart and trying to listen to the response using HTTP get. I can access the response when I ping the I/P in browser but when trying to access in a demo app i get the error
SocketException: OS Error: Connection refused, errno = 111, address = 127.0.0.1, port = 36000
My Server code is as below :
class ServerUtilities {
static Directory _appDirectory;
static HttpServer _server;
static File _file;
ServerUtilities._();
static ServerUtilities _obj;
static ServerUtilities instance() {
if (_obj == null) _obj = ServerUtilities._();
return _obj;
}
Future<Directory> setAppDirectory() async {
return await getApplicationDocumentsDirectory();
}
void initializeServer(String address, int port) async {
_appDirectory = await setAppDirectory();
print(_appDirectory.path);
_file = File('${_appDirectory.path}/sample.txt');
_file.writeAsString("Hiii ", mode: FileMode.append);
_server = await HttpServer.bind(address, port);
print("Server initialized - " + address + ":" + port.toString());
await for (var req in _server) {
if (await _file.exists()) {
print("file exist");
// req.response.headers.contentType = ContentType.text;
await _file.openRead().pipe(req.response);
}
}
}
void stopServer() async {
await _server.close().catchError(
(e) {
print(e);
},
).then(
(value) => {
print("Server stopped "),
},
);
}
}
The server got initialized and everything works fine and can open the provided IP in my mobile browser and it works well but when trying to use Http.get i got the above error.
This is my main.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
ServerUtilities.instance().initializeServer('127.0.0.1', 8010);
runApp(
MaterialApp(
home: MyApp(),
),
);
}
And this is how I am trying to access, And I am getting the above-specified error.
FutureBuilder(
future: http.get("http://127.0.0.1:8010"),
builder: (context, data) {
if (data.hasData)
return Text(
data.toString(),
style: TextStyle(fontSize: 20),
);
else if (data.hasError) {
print(data.error);
return Text(
data.error.toString(),
style: TextStyle(fontSize: 20),
);
} else
return Text(
"No data",
style: TextStyle(fontSize: 20),
);
}),
This error comes when the Server is not running. So please check whether initializeServer method is working correctly or not.
Related
so i have this function which detect if there is connection or not . if yes the var activeConnection is true else false . So if the connection is working i'm going to call a method sendEmail() which work with the plugin mailer . My problem is when i activated the WIFI it can send the email then if i turn it off an exception is shown
E/flutter ( 5347): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)]
Unhandled Exception: SocketException: Failed host lookup:
'smtp.gmail.com' (OS Error: No address associated with hostname, errno
= 7)
in this case activeConnection is true but when it try to send the email it can't find the connection . if i turn off the wifi and wait for a moment before i send the email it can detect that there is no wifi so i tried to add a sleep function before it check the connection but i'm facing the same problem .
this is the code :
Future checkUserConnection() async {
try {
//sleep(const Duration(seconds: 10));
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
setState(() {
activeConnection = true;
print(activeConnection);
});
}
} on SocketException catch (_) {
setState(() {
activeConnection = false;
print(activeConnection);
});
}
//print(activeConnection);
}
and this is where i call my function
onTap: () {
checkUserConnection();
print(activeConnection);
if (activeConnection) {
sendEmail();
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
false, "email sended ", Icons.error_outline));
} else {
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
true,
"check your internet connection !!!",
Icons.error_outline));
}
print("hello");
},
You have to make async function like this:
Future<bool> checkUserConnection() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
} on SocketException catch (_) {
return false;
}
}
After that onTap() you have to code like this:
onTap: () {
checkUserConnection().then((activeConnection){
if (activeConnection) {
sendEmail();
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
false, "email sended ", Icons.error_outline));
} else {
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
true, "check your internet connection !!!",
Icons.error_outline));
}
});
}
I'm working on a Flutter project in which I have to receive a message via using Stomp Client via SockJS. This is working fine, but I want to use the data I'm receiving and add it into the list view builder. I have one screen where are all the chat messages are showing up from an API which is receiving data from DB.
I need help with list view builder to refresh it whenever we receive data from Stomp client.
//Stomp_client//
import 'dart:async';
import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:XXXXXXXXXXXXXXX/api/message_api_service.dart';
import 'package:XXXXXXXXXXXXXXX/models/message_model.dart';
import 'package:XXXXXXXXXXXXXXX/screens/chat_screen.dart';
import 'package:XXXXXXXXXXXXXXX/widgets/messageCard_Sender.dart';
import 'package:stomp_dart_client/stomp.dart';
import 'package:stomp_dart_client/stomp_config.dart';
import 'package:stomp_dart_client/stomp_frame.dart';
String access_token;
String chatroomId;
String chatroomAccKey;
int uid;
Data latestmsg;
void onConnectCallback(StompFrame connectFrame) {
print("Connected");
print("/topic/conversations." + chatroomId);
client.subscribe(
destination: "/topic/conversations." + chatroomId,
headers: {'Authorization': 'Bearer $access_token'},
callback: (StompFrame connectFrame) {
print("DATA RECIEVED: " + connectFrame.body);
latestmsg = Data.fromJson(json.decode(connectFrame.body));
print(latestmsg);
},
);
Timer.periodic(Duration(seconds: 2), (_) {
client.send(
destination: '/app/chat.$chatroomId',
body: json.encode({'a': 123}),
);
});
}
StompClient client = StompClient(
config: StompConfig.SockJS(
url:
'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/sockjs',
onConnect: onConnectCallback,
beforeConnect: () async {
print('waiting to connect...');
await Future.delayed(Duration(milliseconds: 200));
print('connecting...');
},
heartbeatIncoming: Duration(seconds: 0),
heartbeatOutgoing: Duration(seconds: 1),
onWebSocketError: (dynamic error) => print(error.toString()),
stompConnectHeaders: {'Authorization': 'Bearer $access_token'},
webSocketConnectHeaders: {'Authorization': 'Bearer $access_token'},
));
void main(String token, String chatroomid, String chatroomAcKey) {
chatroomAccKey = chatroomAcKey;
chatroomId = chatroomid;
print(chatroomid);
access_token = token;
client.activate();
}
//API for MESSAGE//
import 'package:dio/dio.dart';
import 'package:XXXXXXXXXX/models/message_model.dart';
class message_api_service {
String _token;
String _accessKey;
String _chatroomID;
int newSize;
int oldSize;
String _url = "http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
Dio _dio;
message_api_service(String token, String accessKey, String chatroomID,
int _newSize, int _oldSize) {
this._dio = Dio()..options.headers['Authorization'] = "Bearer ${token}";
this._token = token;
this._accessKey = accessKey;
this._chatroomID = chatroomID;
this.newSize = _newSize;
this.oldSize = _oldSize;
}
Future<Data> fetchallmessages() async {
try {
Response response = await _dio.get(_url, queryParameters: {
'accessKey': "${_accessKey}",
'chatRoomId': "${_chatroomID}",
'newSize': "${newSize}",
'oldSize': " $oldSize"
});
message_model mModel = message_model.fromJson(response.data);
return mModel.data;
} on DioError catch (e) {
print(e);
}
throw ("error fetching data");
}
}
//Screen where i m calling stomp client activate//
#override
void initState() {
super.initState();
main(widget.token, widget.user.chatRoomId, widget.user.roomAccessKey); //to acctivate stomp client.
}
//where i was calling message api//
Expanded(
child: Container(
child: FutureBuilder<Data>(
future: message_api_service(widget.token,
widget.user.roomAccessKey, widget.user.chatRoomId, 50, 0)
.fetchallmessages(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
controller: _controller,
itemCount: snapshot.data.messages.length,
itemBuilder: (context, index) {
return messageCard(
snapshot.data.messages[index],
snapshot.data.messages[index].sender,
widget.ismyEmail,
widget.isMyUID);
});
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
)),
),
Your class needs to be StatefulWidget and you need to make use of StreamBuilder for it automatically update the UI, whenever the changes are detected.
I'm trying to serve local content from assets through https, in order to gain access to features like webrtc which require ssl.
Since the local app server provided in flutter_inappwebview
does not handle ssl connections, I've replaced the InAppLocalHostServer class with InAppLocalHostSecureServer with the following code:
import 'dart:io';
import 'dart:async';
import 'package:flutter/services.dart' show rootBundle;
import 'package:mime/mime.dart';
class InAppLocalHostSecureServer {
HttpServer _server;
int _port = 8443;
InAppLocalHostSecureServer({int port = 8443}) {
this._port = port;
}
///Starts a server on http://localhost:[port]/.
///
///**NOTE for iOS**: For the iOS Platform, you need to add the `NSAllowsLocalNetworking` key with `true` in the `Info.plist` file (See [ATS Configuration Basics](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35)):
///```xml
///<key>NSAppTransportSecurity</key>
///<dict>
/// <key>NSAllowsLocalNetworking</key>
/// <true/>
///</dict>
///```
///The `NSAllowsLocalNetworking` key is available since **iOS 10**.
Future<void> start() async {
if (this._server != null) {
throw Exception('Server already started on https://localhost:$_port');
}
var completer = Completer();
runZoned(() async {
SecurityContext context = new SecurityContext();
var chain = await rootBundle.load('assets/certificates/cert.pem');
var key = await rootBundle.load('assets/certificates/key.pem');
context.useCertificateChainBytes(chain.buffer.asInt8List());
context.usePrivateKeyBytes(key.buffer.asInt8List(), password: 'dartdart');
HttpServer.bindSecure('127.0.0.1', _port, context).then((server) {
print('Server running on https://localhost:' + _port.toString());
this._server = server;
server.listen((HttpRequest request) async {
print(request);
var body = List<int>();
var path = request.requestedUri.path;
path = (path.startsWith('/')) ? path.substring(1) : path;
path += (path.endsWith('/')) ? 'index.html' : '';
try {
body = (await rootBundle.load(path)).buffer.asUint8List();
} catch (e) {
print(e.toString());
request.response.close();
return;
}
var contentType = ['text', 'html'];
if (!request.requestedUri.path.endsWith('/') &&
request.requestedUri.pathSegments.isNotEmpty) {
var mimeType =
lookupMimeType(request.requestedUri.path, headerBytes: body);
if (mimeType != null) {
contentType = mimeType.split('/');
}
}
request.response.headers.contentType =
ContentType(contentType[0], contentType[1], charset: 'utf-8');
request.response.add(body);
request.response.close();
});
completer.complete();
});
}, onError: (e, stackTrace) {
print('Error: $e $stackTrace');
});
return completer.future;
}
///Closes the server.
Future<void> close() async {
if (this._server != null) {
await this._server.close(force: true);
print('Server running on http://localhost:$_port closed');
this._server = null;
}
}
}
Most of the code is a copy paste of the original class.
What I changed is that I call HttpServer.bindSecure instead of HttpServer.bind and I provide openssl certificate and key.
The server seems to start without error logged in the console, but I cannot access it.
Here is the client code that try to access a local url:
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'InAppLocalHostSecureServer.dart';
class WebAudioTest extends StatefulWidget {
#override
_WebAudioTestState createState() => _WebAudioTestState();
}
class _WebAudioTestState extends State<WebAudioTest> {
InAppWebViewController webView;
InAppLocalHostSecureServer localhostServer;
String url = "https://127.0.0.1:8443/assets/web/index.html";
#override
void initState() {
super.initState();
this.init();
}
void init() async {
this.localhostServer = new InAppLocalHostSecureServer();
await localhostServer.start();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Web Audio Test'),
),
body: InAppWebView(
initialUrl: url,
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)),
onWebViewCreated: (InAppWebViewController c) {
webView = c;
},
onConsoleMessage: (controller, consoleMessage) {
print("CONSOLE MESSAGE: " + consoleMessage.message);
},
),
);
}
}
No error appears in the console but the flutter page display the following error message:
net::ERR_CONNECTION_REFUSED
Any help is welcome.
Ok, to answer my own questions:
the problem I had was simply that I build the InAppWebView too early, before the server has finished to launch. The solution is easy, just set a flag to true when the server is launched, and create the InAppWebView only when the flag is true.
Beside this, WebRTC works without https on localhost, I tested it on Android and iOS. So no need for local https for this use case.
But anyway if for any other reason someone needs to to serve https local content, the code in this post can serve as a basis for this.
Inconsistent behavior of HttpServer in Flutter/Dart ! The following code runs fine if executed as a desktop application but returns an error as Unsupported Operation at ServerSocket.bind if executed as a web server or through browser !
import 'package:flutter/material.dart';
import 'dart:io';
void main()
{
runApp(MaterialApp(home: Home(),));
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
String statusText = "Start Server";
startServer()
async{
setState(() {
statusText = "Starting server on Port : 8088";
});
print("Attempting bind");
// other attempts with same result
// var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 8088, shared: true);
// var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 8089, shared: true);
// var server = await HttpServer.bind(InternetAddress.anyIPv4, 0, shared: true);
// var server = await HttpServer.bind("0.0.0.0", 35568, shared: true);
var serverSocket = await ServerSocket.bind("0.0.0.0", 0);
var server = HttpServer.listenOn(serverSocket);
setState(() {
statusText = "Server running on IP : "+server.address.toString()+" On Port : "+server.port.toString();
});
print("Server running on IP : "+server.address.toString()+" On Port : "+server.port.toString());
await for (var request in server) {
setState(() {
statusText = request.requestedUri.toString();
});
request.response.headers.contentType = new ContentType("text", "plain", charset: "utf-8");
request.response.write("hello world");
request.response.close();
print("Response served\n");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: (){startServer();},
child: Text(statusText),)],),));
}
}
Testing on
Ubuntu 16.04 lts
Tested with and without firewall
Need this to host a web service
Any other methods available within Flutter are welcome
Haven't yet tried with threading
First, dart:io are not supported in web browsers so that explain your problem with running the code in browsers:
Important: Browser-based applications can't use this library. Only servers, command-line scripts, and Flutter mobile apps can import and use dart:io.
https://api.dart.dev/stable/2.8.4/dart-io/dart-io-library.html
Second, your code is very complicated if the purpose is to create a simple HTTP server running on a headless server. I have simplified your code so it does no longer depend on Flutter and can just be executed with dart:
import 'dart:io';
void main() {
startServer();
}
Future<void> startServer() async {
print("Starting server on Port : 8088");
print("Attempting bind");
final server = await HttpServer.bind("0.0.0.0", 8080);
print("Server running on IP : ${server.address} On Port : ${server.port}");
await for (final request in server) {
print(request.requestedUri);
request.response
..headers.contentType = ContentType("text", "plain", charset: "utf-8")
..write("hello world");
await request.response.flush();
await request.response.close();
print("Response served\n");
}
}
I am new in BLOC and I am trying to read respond from api.. but whenever I call stream builder... my widget always stops in wait... here is my code
here is api provider file
class Provider {
final _url = '...';
Future<List<LoginRespon>> login(a, b) async {
List<LoginRespon> datalogin = [];
try {
bool trustSelfSigned = true;
HttpClient httpClient = new HttpClient()
..badCertificateCallback =
((X509Certificate cert, String host, int port) =>
trustSelfSigned);
IOClient http = new IOClient(httpClient);
final response = await http.post(_url,
headers: {
HttpHeaders.contentTypeHeader: 'application/json',
},
body: json.encode({
"aa": a,
"bb": b,
}));
Map<String, dynamic> responseJson = json.decode(response.body);
if (responseJson["status"] == "200") {
datalogin.add(LoginRespon(
status: responseJson['status'],
data: Data(
name: responseJson['data']['name'],
position: responseJson['data']['pos'])));
return datalogin;
} else {
print("ppp");
}
} on Exception {
rethrow;
}
return datalogin;
}
}
and here is for stream builder
isClick
? StreamBuilder(
stream: bloc.login(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(snapshot.data);
return Text("success");
} else if (snapshot.hasError) {
return Text(
snapshot.error.toString());
}
return Text("wait..");
},
)
: FlatButton(
child: Text("Login"),
onPressed: () {
setState(() {
isClick = true;
});
},
),
is there a way so that I can call print(snapshot.data) inside if (snapshot.hasData)
You need to pass argument which required in method otherwise it will not successfully responce (200) and it will throw error.