signedUrl static method
url with a signature query param, so the link can not be
changed. Check it with the ValidateSignature middleware. With
expires, the url also has an expires param (unix seconds) and
stops working after that time.
The url is absolute by default: baseUrl (default: APP_URL of
the env, like https://example.com) is put in front, and the host
is signed too. Use absolute: false to sign the path and query
only, and then ValidateSignature(absolute: false).
Route.signedUrl('unsubscribe', params: <String, Object>{'user': 5});
// https://example.com/unsubscribe/5?signature=...
Route.signedUrl('download', expires: Duration(hours: 1));
Implementation
static String signedUrl(
String name, {
Map<String, Object?> params = const <String, Object?>{},
Map<String, Object?> query = const <String, Object?>{},
Duration? expires,
bool absolute = true,
String? baseUrl,
}) {
if (query.containsKey('signature')) {
throw ArgumentError('"signature" is a reserved query param.');
}
Map<String, Object?> all = <String, Object?>{
...query,
if (expires != null)
'expires': DateTime.now().add(expires).millisecondsSinceEpoch ~/ 1000,
};
String path = url(name, params: params, query: all);
if (absolute) {
String base = baseUrl ?? Env.get<String>('APP_URL', '');
if (base.isEmpty) {
throw ArgumentError(
'Route.signedUrl needs a host for an absolute url. Set APP_URL '
'in the env, give baseUrl, or use absolute: false.',
);
}
if (base.endsWith('/')) base = base.substring(0, base.length - 1);
path = '$base$path';
}
String signature = ValidateSignature.sign(path);
return '$path${path.contains('?') ? '&' : '?'}signature=$signature';
}