@@ -93,10 +93,30 @@ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterfac
9393 */
9494 private function generateMatchMethod ($ supportsRedirections )
9595 {
96- $ code = rtrim ($ this ->compileRoutes ($ this ->getRoutes (), $ supportsRedirections ), "\n" );
97-
9896 return <<<EOF
9997 public function match( \$rawPathinfo)
98+ {
99+ try {
100+ return \$this->matchWithoutTrailingSlashManagement( \$rawPathinfo);
101+ } catch (MethodNotAllowedException \$e) {
102+ throw \$e;
103+ } catch (ResourceNotFoundException \$e) {
104+ return \$this->matchWithTrailingSlashManagement( \$rawPathinfo);
105+ }
106+ }
107+
108+ {$ this ->generateMatchWithTrailingSlashManagement ($ supportsRedirections )}
109+
110+ {$ this ->generateMatchWithoutTrailingSlashManagement ($ supportsRedirections )}
111+ EOF ;
112+ }
113+
114+ private function generateMatchWithTrailingSlashManagement ($ supportsRedirections )
115+ {
116+ $ code = rtrim ($ this ->compileRoutes ($ this ->getRoutes (), $ supportsRedirections , true ), "\n" );
117+
118+ return <<<EOF
119+ public function matchWithTrailingSlashManagement( \$rawPathinfo)
100120 {
101121 \$allow = [];
102122 \$pathinfo = rawurldecode( \$rawPathinfo);
@@ -109,6 +129,30 @@ public function match(\$rawPathinfo)
109129 \$canonicalMethod = 'GET';
110130 }
111131
132+ $ code
133+
134+ throw 0 < count( \$allow) ? new MethodNotAllowedException(array_unique( \$allow)) : new ResourceNotFoundException();
135+ }
136+ EOF ;
137+ }
138+
139+ private function generateMatchWithoutTrailingSlashManagement ($ supportsRedirections )
140+ {
141+ $ code = rtrim ($ this ->compileRoutes ($ this ->getRoutes (), $ supportsRedirections , false ), "\n" );
142+
143+ return <<<EOF
144+ public function matchWithoutTrailingSlashManagement( \$rawPathinfo)
145+ {
146+ \$allow = [];
147+ \$pathinfo = rawurldecode( \$rawPathinfo);
148+ \$context = \$this->context;
149+ \$request = \$this->request ?: \$this->createRequest( \$pathinfo);
150+ \$requestMethod = \$canonicalMethod = \$context->getMethod();
151+
152+ if ('HEAD' === \$requestMethod) {
153+ \$canonicalMethod = 'GET';
154+ }
155+
112156$ code
113157
114158 throw 0 < count( \$allow) ? new MethodNotAllowedException(array_unique( \$allow)) : new ResourceNotFoundException();
@@ -124,7 +168,7 @@ public function match(\$rawPathinfo)
124168 *
125169 * @return string PHP code
126170 */
127- private function compileRoutes (RouteCollection $ routes , $ supportsRedirections )
171+ private function compileRoutes (RouteCollection $ routes , $ supportsRedirections, $ trailingSlashManagement = true )
128172 {
129173 $ fetchedHost = false ;
130174 $ groups = $ this ->groupRoutesByHostRegex ($ routes );
@@ -141,7 +185,7 @@ private function compileRoutes(RouteCollection $routes, $supportsRedirections)
141185 }
142186
143187 $ tree = $ this ->buildStaticPrefixCollection ($ collection );
144- $ groupCode = $ this ->compileStaticPrefixRoutes ($ tree , $ supportsRedirections );
188+ $ groupCode = $ this ->compileStaticPrefixRoutes ($ tree , $ supportsRedirections, $ trailingSlashManagement );
145189
146190 if (null !== $ regex ) {
147191 // apply extra indention at each line (except empty ones)
@@ -184,7 +228,7 @@ private function buildStaticPrefixCollection(DumperCollection $collection)
184228 *
185229 * @return string PHP code
186230 */
187- private function compileStaticPrefixRoutes (StaticPrefixCollection $ collection , $ supportsRedirections , $ ifOrElseIf = 'if ' )
231+ private function compileStaticPrefixRoutes (StaticPrefixCollection $ collection , $ supportsRedirections , $ trailingSlashManagement , $ ifOrElseIf = 'if ' )
188232 {
189233 $ code = '' ;
190234 $ prefix = $ collection ->getPrefix ();
@@ -200,7 +244,7 @@ private function compileStaticPrefixRoutes(StaticPrefixCollection $collection, $
200244 $ code .= $ this ->compileStaticPrefixRoutes ($ route , $ supportsRedirections , $ ifOrElseIf );
201245 $ ifOrElseIf = 'elseif ' ;
202246 } else {
203- $ code .= $ this ->compileRoute ($ route [1 ]->getRoute (), $ route [1 ]->getName (), $ supportsRedirections , $ prefix )."\n" ;
247+ $ code .= $ this ->compileRoute ($ route [1 ]->getRoute (), $ route [1 ]->getName (), $ supportsRedirections , $ trailingSlashManagement , $ prefix )."\n" ;
204248 $ ifOrElseIf = 'if ' ;
205249 }
206250 }
@@ -226,7 +270,7 @@ private function compileStaticPrefixRoutes(StaticPrefixCollection $collection, $
226270 *
227271 * @throws \LogicException
228272 */
229- private function compileRoute (Route $ route , $ name , $ supportsRedirections , $ parentPrefix = null )
273+ private function compileRoute (Route $ route , $ name , $ supportsRedirections , $ trailingSlashManagement , $ parentPrefix = null )
230274 {
231275 $ code = '' ;
232276 $ compiledRoute = $ route ->compile ();
@@ -236,7 +280,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
236280 $ hostMatches = false ;
237281 $ methods = $ route ->getMethods ();
238282
239- $ supportsTrailingSlash = $ supportsRedirections && (!$ methods || \in_array ('GET ' , $ methods ));
283+ $ supportsTrailingSlash = $ supportsRedirections && (!$ methods || \in_array ('GET ' , $ methods )) && $ trailingSlashManagement ;
240284 $ regex = $ compiledRoute ->getRegex ();
241285
242286 if (!\count ($ compiledRoute ->getPathVariables ()) && false !== preg_match ('#^(.)\^(?P<url>.*?)\$\1# ' .('u ' === substr ($ regex , -1 ) ? 'u ' : '' ), $ regex , $ m )) {
0 commit comments