import 'dart:io'; import 'dart:async'; import 'package:flutter/services.dart' show rootBundle; import 'mime_type_resolver.dart'; ///This class allows you to create a simple server on `http://localhost:[port]/` in order to be able to load your assets file on a server. The default [port] value is `8080`. class InAppLocalhostServer { HttpServer? _server; int _port = 8080; InAppLocalhostServer({int port = 8080}) { 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 ///NSAppTransportSecurity /// /// NSAllowsLocalNetworking /// /// ///``` ///The `NSAllowsLocalNetworking` key is available since **iOS 10**. Future start() async { if (this._server != null) { throw Exception('Server already started on http://localhost:$_port'); } var completer = Completer(); runZonedGuarded(() { HttpServer.bind('127.0.0.1', _port).then((server) { print('Server running on http://localhost:' + _port.toString()); this._server = server; server.listen((HttpRequest request) async { var body = [] as List; 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 = MimeTypeResolver.lookup(request.requestedUri.path); 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(); }); }, (e, stackTrace) => print('Error: $e $stackTrace')); return completer.future; } ///Closes the server. Future close() async { if (this._server != null) { await this._server!.close(force: true); print('Server running on http://localhost:$_port closed'); this._server = null; } } }