I'm working on a Dart HttpServer using SSL, which looks something like this:
class Server {
//The path for the database is relative to the code's entry point (main.dart)
static const String CERTIFICATE_DB_PATH = '../lib/server/';
static const String CERTIFICATE_DB_PASS = '*******';
static const String CERTIFICATE_NAME = 'CN=mycert';
Future start() async {
SecureSocket.initialize(database: CERTIFICATE_DB_PATH, password: CERTIFICATE_DB_PASS);
httpServer = await HttpServer.bindSecure(ADDRESS, PORT, certificateName: CERTIFICATE_NAME);
listenSubscription = httpServer.listen(onRequest, onError: onError);
}
//more server code here
}
This all works exactly as expected, so no problems with the actual certificate or server code. The part that I'm having problems with is mentioned in that first comment. The CERTIFICATE_DB_PATH seems to be relative not to the file the Server class is defined in, but rather to the file that contains the main() method. This means that when I try to write a unit test for this class, the path is no longer pointing to the correct directory. If this were an import, I'd use the package:packageName/path/to/cert syntax, but it doesn't seem that applies here. How can I specify the path of the certificate in a way that will work with multiple entry points (actually running the server vs unit tests)?
I don't think there is a way to define the path so it is relative to the source file.
What you can do is to change the current working directory either before you run main() or pass a working directory path as argument to main() and let main() make this directory the current working directory.
Directory.current = someDirectory;
Related
Im currently using a global-setup.ts file to load a url via playwright.
await page.goto('https://test1.com/');
I am also doing extra code inside here and storing the state of my object (All works as expected)
My playwright.config.ts file references the globalsetup and this all works as expected.
In my Config file I also set baseUrl however, I am struggling on a way to get the baseUrl passed to my global-setup.ts file instead of hardcoding it.
Thanks!
Inside your global setup, you can access the baseURL like that:
import { FullConfig } from '#playwright/test';
async function globalSetup(config: FullConfig) {
console.log(config.projects[0].use.baseURL);
}
export default globalSetup
See here: https://playwright.dev/docs/api/class-testconfig/
I'm looking for the right way to externalize the settings in my server Dart application.
In Java the common way would be a property file. Exists something similar in Dart?
You can just use a Dart script for your settings. No point in using a different format if there is no specific reason.
With a simple import you have it available in a typed way.
When the Resource class is implemented, I would just use a JSON file that is deployed with my program.
You could use a global variables, for example:
DB_URL = 'localhost:5432/mydb';
DB_PASS = 'my_pass';
then you could create a different configuration file for every enviroment. For example, for production you could create a production_config.dart which could contains:
loadConfig() {
DB_URL = '123.123.123.123:5432/mydb';
DB_PASS = 'my_prod_pass';
}
Then in your main function you could call production_config.loadConfig if environment is production, for example:
import 'production_config.dart' as prodConfig;
main(List<String> args) {
var ENV = getEnvFromArgs(args);
if(ENV == 'PROD') {
prodConfig.loadConfig();
}
//do other stuff here
}
In that way if you want to change from development to production you only need to pass an argument to your dart program for example:
dart myprogram.dart -env=PROD
The advantages of this approach are that you don't need to create a separate properties, json or yaml file for this, and you don't need to parse them. Furthermore the properties are type-ckecked.
I like putting configuration in a Dart class like what Günter Zöchbauer was talking about, but there is also the option of using the safe_config package. With this you enter the values in a yaml file. Quoting from the docs:
You define a subclass of Configuration with those properties:
class ApplicationConfiguration extends Configuration {
ApplicationConfiguration(String fileName) :
super.fromFile(File(fileName));
int port;
String serverHeader;
}
Your YAML file should contain those two, case-sensitive keys:
port: 8000
serverHeader: booyah/1
To read your configuration file:
var config = new ApplicationConfiguration("config.yaml");
print("${config.port}"); // -> 8000
print("${config.serverHeader}"); // -> "booyah/1"
See also an example from a setup in Aqueduct.
main() {
var env = const String.fromEnvironment("ENV", defaultValue: "local");
print("Env === " + env);
}
Give environment as option while running Dart App
pub serve --port=9002 --define ENV=dev
References:
http://blog.sethladd.com/2013/12/compile-time-dead-code-elimination-with.html
https://github.com/dart-lang/sdk/issues/27998
I have two packages: webserver and utils which provides assets to webserver.
The webserver needs access to static files inside utils. So I have this setup:
utils/
lib/
static.html
How can I access the static.html file in one of my dart scripts in webserver?
EDIT: What I tried so far, is to use mirrors to get the path of the library, and read it from there. The problem with that approach is, that if utils is included with package:, the url returned by currentMirrorSystem().findLibrary(#utils).uri is a package uri, that can't be transformed to an actual file entity.
Use the Resource class, a new class in Dart SDK 1.12.
Usage example:
var resource = new Resource('package:myapp/myfile.txt');
var contents = await resource.loadAsString();
print(contents);
This works on the VM, as of 1.12.
However, this doesn't directly address your need to get to the actual File entity, from a package: URI. Given the Resource class today, you'd have to route the bytes from loadAsString() into the HTTP server's Response object.
I tend to use Platform.script or mirrors to find the main package top folder (i.e. where pubspec.yaml is present) and find imported packages exported assets. I agree this is not a perfect solution but it works
import 'dart:io';
import 'package:path/path.dart';
String getProjectTopPath(String resolverPath) {
String dirPath = normalize(absolute(resolverPath));
while (true) {
// Find the project root path
if (new File(join(dirPath, "pubspec.yaml")).existsSync()) {
return dirPath;
}
String newDirPath = dirname(dirPath);
if (newDirPath == dirPath) {
throw new Exception("No project found for path '$resolverPath");
}
dirPath = newDirPath;
}
}
String getPackagesPath(String resolverPath) {
return join(getProjectTopPath(resolverPath), 'packages');
}
class _TestUtils {}
main(List<String> arguments) {
// User Platform.script - does not work in unit test
String currentScriptPath = Platform.script.toFilePath();
String packagesPath = getPackagesPath(currentScriptPath);
// Get your file using the package name and its relative path from the lib folder
String filePath = join(packagesPath, "utils", "static.html");
print(filePath);
// use mirror to find this file path
String thisFilePath = (reflectClass(_TestUtils).owner as LibraryMirror).uri.toString();
packagesPath = getPackagesPath(thisFilePath);
filePath = join(packagesPath, "utils", "static.html");
print(filePath);
}
To note that since recently Platform.script is not reliable in unit test when using the new test package so you might use the mirror tricks that I propose above and explained here: https://github.com/dart-lang/test/issues/110
I'm writing a Jenkins plugin and i'm using build.getWorkspace() to get the path to the current workspace. The issue is that this returns a FilePath object.
How can i convert this to a File object?
Although I haven't tried this, according to the javadoc you can obtain the URI from which you can then create a file: File myFile = new File(build.getWorkspace().toURI())
Please use the act function and call your own FileCallable implementation if your plugin should work for master and slaves. For more information check the documentation, chapter "Using FilePath smartly" or this stackoverflow answer.
Code example (source):
void someMethod(FilePath file) {
// make 'file' a fresh empty directory.
file.act(new Freshen());
}
// if 'file' is on a different node, this FileCallable will
// be transferred to that node and executed there.
private static final class Freshen implements FileCallable<Void> {
private static final long serialVersionUID = 1;
#Override public Void invoke(File f, VirtualChannel channel) {
// f and file represent the same thing
f.deleteContents();
f.mkdirs();
return null;
}
}
This approach
File myFile = new File(build.getWorkspace().toURI()) is not the correct solution. I don't know why this has been an accepted anwser till date.
The approach mentioned by Sascha Vetter is correct, taking the reference from official Jenkins javadocs
,which clearly says and I quote
Unlike File, which always implies a file path on the current computer, FilePath represents a file path on a specific agent or the controller.
So being an active contributor to Jenkins community, I would reference the answer given by Sascha Vetter.
PS. Reputation point criteria makes me unable to up-vote the correct answer.
I would like to list all the contents of a directory (on the file system) using Dart. How can I do this?
How to list the contents of a directory in Dart
final dir = Directory('path/to/directory');
final List<FileSystemEntity> entities = await dir.list().toList();
This creates a Directory from a path. Then it converts it to a list of FileSystemEntity, which can be a File, a Directory, or a Link. By default subdirectories are not listed recursively.
If you want to print that list, then add this line:
entities.forEach(print);
If you want to only get the files then you could do it like so:
final Iterable<File> files = entities.whereType<File>();
The API has changed and I have updated the async code for M4 release (0.5.16_r23799 ):
Future<List<FileSystemEntity>> dirContents(Directory dir) {
var files = <FileSystemEntity>[];
var completer = Completer<List<FileSystemEntity>>();
var lister = dir.list(recursive: false);
lister.listen (
(file) => files.add(file),
// should also register onError
onDone: () => completer.complete(files)
);
return completer.future;
}
The list method returns a Stream where each emitted event is a directory entry:
Directory dir = Directory('.');
// execute an action on each entry
dir.list(recursive: false).forEach((f) {
print(f);
});
As the name suggest, listSync method is the blocking version:
// create a list of entries
List<FileSystemEntity> entries = dir.listSync(recursive: false).toList();
What method to use depends on application context. A note directly from the docs:
Unless you have a specific reason for using the synchronous version of a method, prefer the asynchronous version to avoid blocking your program.
This answer is out of date. Please see the accepted answer.
There are two ways to list the contents of a directory using the Dart VM and the dart:io library.
(note: the following only works in the Dart VM when running on the command-line or as a server-side app. This does not work in a browser or when compiled to JavaScript.)
Setup
First, you need to import the dart:io library. This library contains the classes required to access files, directories, and more.
import 'dart:io';
Second, create a new instance of the Directory class.
var dir = new Directory('path/to/my/dir');
Listing contents in a script
The easiest way is to use the new listSync method. This returns a List of contents. By default this does not recurse.
List contents = dir.listSync();
for (var fileOrDir in contents) {
if (fileOrDir is File) {
print(fileOrDir.name);
} else if (fileOrDir is Directory) {
print(fileOrDir.path);
}
}
If you want to recurse through directories, you can use the optional parameter recursive.
List allContents = dir.listSync(recursive: true);
WARNING if your directory structure has circular symlinks, the above code will crash because it's following symlinks recursively.
This method, using listSync, is especially useful when you are writing a shell script, command-line utility, or similar app or script with Dart.
Listing contents in a server
A second way to list the contents of a directory is to use the async version of list. You would use this second method when you need to list a directory in response to, say, an HTTP request. Remember that each of Dart's isolates runs in a single thread. Any long running process can block the event loop. When interactivity is important, or serving lots of clients from a single Dart script, use the async version.
With the async version, dir.list() returns a DirectoryLister. You can register three different callbacks on DirectoryLister:
onFile: called when a file or directory is encountered
onDone: called when the directory lister is done listing contents
onError: called when the lister encounters some error
Here is a simple function that returns a Future of a list of strings, containing file names in a directory:
Future<List<String>> dirContents(Directory dir) {
var filenames = <String>[];
var completer = new Completer();
var lister = dir.list();
lister.onFile = (filename) => filenames.add(filename);
// should also register onError
lister.onDone = (_) => completer.complete(filenames);
return completer.future;
}
Of course, this method is perfect for servers, it's more cumbersome for simple scripts.
Luckily, Dart supports both methods for you to use!
Inside and asynchronous function write this
List<FileSystemEntity> allContents = await Directory("folder/path").list().toList();
Now you have a list with all of the contents
Here is my version using async/await, returning a List of Files only:
List<File> filesInDirectory(Directory dir) async {
List<File> files = <File>[];
await for (FileSystemEntity entity in dir.list(recursive: false, followLinks: false)) {
FileSystemEntityType type = await FileSystemEntity.type(entity.path);
if (type == FileSystemEntityType.FILE) {
files.add(entity);
print(entity.path);
}
}
return files;
}
With this function you can print all the directories and files of a directory.
You just need to pass a specific path.
Future listDir(String folderPath) async {
var directory = new Directory(folderPath);
print(directory);
var exists = await directory.exists();
if (exists) {
print("exits");
directory
.list(recursive: true, followLinks: false)
.listen((FileSystemEntity entity) {
print(entity.path);
});
}
}
To get a list of file names with a certain string, you can use this code:
String directory = (await getApplicationDocumentsDirectory()).path;
List<FileSystemEntity> files = Directory(directory).listSync(recursive: false);
List<String> filePaths = [];
for (var fileSystemEntity in files) {
if (basename(fileSystemEntity.path).contains('mystring')) {
filePaths.add(fileSystemEntity.path);
}
}
You can use the basename function if you need just the file name, and not the whole path.
To get all files with given extension:
import 'package:path/path.dart' as p;
Future<List<File>> getAllFilesWithExtension(String path, String extension) async {
final List<FileSystemEntity> entities = await Directory(path).list().toList();
return entities.whereType<File>().where((element) => p.extension(element.path) == extension).toList();
}