signedUrl static method

String signedUrl(
  1. String name, {
  2. Map<String, Object?> params = const <String, Object?>{},
  3. Map<String, Object?> query = const <String, Object?>{},
  4. Duration? expires,
  5. bool absolute = true,
  6. String? baseUrl,
})

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';
}