Fix an issue where GoRoutes with only a redirect were disallowed. (#2620)

diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md
index 3368d08..1746ece 100644
--- a/packages/go_router/CHANGELOG.md
+++ b/packages/go_router/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 4.5.1
+
+- Fixes an issue where GoRoutes with only a redirect were disallowed
+  (flutter/flutter#111763)
+
 ## 4.5.0
 
 - Adds ShellRoute for nested navigation support (flutter/flutter#99126)
diff --git a/packages/go_router/lib/src/redirection.dart b/packages/go_router/lib/src/redirection.dart
index 03d27be..be09bb2 100644
--- a/packages/go_router/lib/src/redirection.dart
+++ b/packages/go_router/lib/src/redirection.dart
@@ -6,6 +6,7 @@
 import 'logging.dart';
 import 'match.dart';
 import 'matching.dart';
+import 'typedefs.dart';
 
 /// A GoRouter redirector function.
 // TODO(johnpryan): make redirector async
@@ -76,7 +77,12 @@
     assert(topRoute is GoRoute,
         'Last RouteMatch should contain a GoRoute, but was ${topRoute.runtimeType}');
     final GoRoute topGoRoute = topRoute as GoRoute;
-    final String? topRouteLocation = topGoRoute.redirect(
+    final GoRouterRedirect? redirect = topGoRoute.redirect;
+    if (redirect == null) {
+      break;
+    }
+
+    final String? topRouteLocation = redirect(
       GoRouterState(
         configuration,
         location: currentMatches.location.toString(),
diff --git a/packages/go_router/lib/src/route.dart b/packages/go_router/lib/src/route.dart
index ca0497c..98dd5f5 100644
--- a/packages/go_router/lib/src/route.dart
+++ b/packages/go_router/lib/src/route.dart
@@ -124,17 +124,12 @@
     this.builder,
     this.pageBuilder,
     this.parentNavigatorKey,
-    this.redirect = _emptyRedirect,
+    this.redirect,
     List<RouteBase> routes = const <RouteBase>[],
   })  : assert(path.isNotEmpty, 'GoRoute path cannot be empty'),
         assert(name == null || name.isNotEmpty, 'GoRoute name cannot be empty'),
-        assert(!(builder == null && pageBuilder == null),
-            'builder or pageBuilder must be provided'),
-        assert(
-            pageBuilder != null ||
-                builder != _invalidBuilder ||
-                redirect != _noRedirection,
-            'GoRoute builder parameter not set\n'),
+        assert(pageBuilder != null || builder != null || redirect != null,
+            'builder, pageBuilder, or redirect must be provided'),
         super._(
           routes: routes,
         ) {
@@ -288,7 +283,7 @@
   /// routes, also known as route guards. One canonical example is user
   /// authentication. See [Redirection](https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/redirection.dart)
   /// for a complete runnable example.
-  final GoRouterRedirect redirect;
+  final GoRouterRedirect? redirect;
 
   /// An optional key specifying which Navigator to display this route's screen
   /// onto.
@@ -305,19 +300,9 @@
   Map<String, String> extractPathParams(RegExpMatch match) =>
       extractPathParameters(_pathParams, match);
 
-  static String? _emptyRedirect(GoRouterState state) => null;
-
   final List<String> _pathParams = <String>[];
 
   late final RegExp _pathRE;
-
-  static String? _noRedirection(GoRouterState state) => null;
-
-  static Widget _invalidBuilder(
-    BuildContext context,
-    GoRouterState state,
-  ) =>
-      const SizedBox.shrink();
 }
 
 /// A route that displays a UI shell around the matching child route.
diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml
index 119e415..fc097cf 100644
--- a/packages/go_router/pubspec.yaml
+++ b/packages/go_router/pubspec.yaml
@@ -1,7 +1,7 @@
 name: go_router
 description: A declarative router for Flutter based on Navigation 2 supporting
   deep linking, data-driven routes and more
-version: 4.5.0
+version: 4.5.1
 repository: https://github.com/flutter/packages/tree/main/packages/go_router
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22
 
diff --git a/packages/go_router/test/go_route_test.dart b/packages/go_router/test/go_route_test.dart
index c20d224..f2de79b 100644
--- a/packages/go_router/test/go_route_test.dart
+++ b/packages/go_router/test/go_route_test.dart
@@ -13,4 +13,8 @@
   test('throws when a path is empty', () {
     expect(() => GoRoute(path: ''), throwsA(isAssertionError));
   });
+
+  test('does not throw when only redirect is provided', () {
+    GoRoute(path: '/', redirect: (_) => '/a');
+  });
 }