-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored pmtiles_server to be generic. This will allow us to spawn …
…other server types.
- Loading branch information
Showing
7 changed files
with
237 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import 'package:test/test.dart'; | ||
|
||
import 'archive_test.dart'; | ||
|
||
// Quis custodiet ipsos custodes? | ||
void main() async { | ||
test('pmtilesServingToUrl', () { | ||
String actual = pmtilesServingToUrl( | ||
'2024/02/01 10:21:28 main.go:152: Serving . on port 8080 and interface 0.0.0.0 with Access-Control-Allow-Origin:'); | ||
expect(actual, "http://0.0.0.0:8080"); | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
import 'package:stream_channel/stream_channel.dart'; | ||
|
||
import 'server_args.dart'; | ||
|
||
/// Gets a free port on the local machine. | ||
/// | ||
/// This is racy, because we don't hold the port open, but it's good enough for | ||
/// our purposes. | ||
/// | ||
/// Borrowed from https://stackoverflow.com/a/14095888/88646 | ||
Future<int> getUnusedPort([InternetAddress? address]) { | ||
return ServerSocket.bind(address ?? InternetAddress.loopbackIPv4, 0) | ||
.then((socket) { | ||
var port = socket.port; | ||
socket.close(); | ||
return port; | ||
}); | ||
} | ||
|
||
/// Spawns a process that can be used for receiving test requests. | ||
/// | ||
/// Use like this: | ||
/// ```dart | ||
/// setUpAll(() async { | ||
/// channel = spawnHybridUri( | ||
/// 'server.dart', | ||
/// stayAlive: true, | ||
/// message: ServerArgs( | ||
/// executable: 'http-server', | ||
/// arguments: ['.'], | ||
/// workingDirectory: 'samples', | ||
/// ).toJson(), | ||
/// ); | ||
/// | ||
/// url = await channel!.stream.first; | ||
/// // Now the server is ready | ||
/// }); | ||
/// | ||
/// tearDownAll(() async { | ||
/// // Tell the server to shutdown and wait for the sink to be closed. | ||
/// if (channel != null) { | ||
/// channel!.sink.add("tearDownAll"); | ||
/// await channel!.sink.done; | ||
/// } | ||
/// }); | ||
/// ``` | ||
/// | ||
hybridMain(StreamChannel channel, Object message) async { | ||
final args = ServerArgs.fromJson(message as Map<String, dynamic>); | ||
|
||
// Find the binary, as Process seems to require a full path. | ||
final executableFullPath = | ||
Process.runSync('which', [args.executable]).stdout.toString().trim(); | ||
|
||
if (executableFullPath.isEmpty) { | ||
throw Exception('Could not find `${args.executable}` binary'); | ||
} | ||
|
||
// Replace any `$port`, with a random port number | ||
final arguments = await Future.wait(args.arguments.map((s) async { | ||
while (s.contains('\$port')) { | ||
final port = await getUnusedPort(); | ||
s = s.replaceFirst('\$port', port.toString()); | ||
} | ||
return s; | ||
})); | ||
|
||
// Invoke the binary | ||
Process process = await Process.start( | ||
executableFullPath, | ||
arguments, | ||
workingDirectory: args.workingDirectory, | ||
includeParentEnvironment: false, | ||
); | ||
|
||
try { | ||
// Wait until it prints the 'available' string. | ||
final stdout = process.stdout.transform(utf8.decoder).asBroadcastStream(); | ||
final url = await stdout.firstWhere((line) => line.contains(args.waitFor)); | ||
|
||
// Then ignore the rest | ||
stdout.drain(); | ||
|
||
// Always print stderr | ||
process.stderr.transform(utf8.decoder).forEach(print); | ||
|
||
// Send the line we found | ||
channel.sink.add(url); | ||
|
||
// Wait for the channel to receive a message telling us to tearDown. | ||
await channel.stream.first; // the received message should be "tearDownAll". | ||
} finally { | ||
// The spawned process may hang around due to | ||
// https://github.com/dart-lang/sdk/issues/53772 :( | ||
|
||
// Cleanup the process | ||
process.kill(); | ||
await process.exitCode; | ||
} | ||
|
||
// and we are done. | ||
channel.sink.close(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import 'package:json_annotation/json_annotation.dart'; | ||
|
||
part 'server_args.g.dart'; | ||
|
||
@JsonSerializable() | ||
class ServerArgs { | ||
final String executable; | ||
final List<String> arguments; | ||
final String? workingDirectory; | ||
|
||
/// We wait for a log line that contains this string. | ||
final String waitFor; | ||
|
||
const ServerArgs({ | ||
required this.executable, | ||
required this.waitFor, | ||
this.arguments = const [], | ||
this.workingDirectory, | ||
}) : assert(executable != ""), | ||
assert(waitFor != ""); | ||
|
||
factory ServerArgs.fromJson(Map<String, dynamic> json) => | ||
_$ServerArgsFromJson(json); | ||
Map<String, dynamic> toJson() => _$ServerArgsToJson(this); | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.