@@ -11,12 +11,14 @@ import { getLanguage, isValidLang } from 'core/i18n/utils';
1111import log from 'core/logger' ;
1212
1313export function prefixMiddleware ( req , res , next , { _config = config } = { } ) {
14+ const URLParts = req . originalUrl . split ( '?' ) ;
15+
1416 // Split on slashes after removing the leading slash.
15- const URLParts = req . originalUrl . replace ( / ^ \/ / , '' ) . split ( '/' ) ;
17+ const URLPathParts = URLParts [ 0 ] . replace ( / ^ \/ / , '' ) . split ( '/' ) ;
1618
1719 // Get lang and app parts from the URL. At this stage they may be incorrect
1820 // or missing.
19- const [ langFromURL , appFromURL ] = URLParts ;
21+ const [ langFromURL , appFromURL ] = URLPathParts ;
2022
2123 // Get language from URL or fall-back to detecting it from accept-language
2224 // header.
@@ -45,14 +47,16 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
4547 let prependedOrMovedApplication = false ;
4648
4749 if ( hasValidLocaleException ) {
48- log . info ( oneLine `Second part of URL is a locale exception (${ URLParts [ 1 ] } );
50+ log . info ( oneLine `Second part of URL is a locale exception (${
51+ URLPathParts [ 1 ]
52+ } );
4953 make sure the clientApp is valid` ) ;
5054
5155 // Normally we look for a clientApp in the second part of a URL, but URLs
5256 // that match a locale exception don't have a locale so we look for the
5357 // clientApp in the first part of the URL.
5458 if ( ! isValidClientApp ( langFromURL , { _config } ) ) {
55- URLParts [ 0 ] = application ;
59+ URLPathParts [ 0 ] = application ;
5660 isApplicationFromHeader = true ;
5761 prependedOrMovedApplication = true ;
5862 }
@@ -65,25 +69,28 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
6569 // * It's valid and we've mapped it e.g: pt -> pt-PT.
6670 // * The lang is invalid but we have a valid application
6771 // e.g. /bogus/firefox/.
68- log . info ( `Replacing lang in URL ${ URLParts [ 0 ] } -> ${ lang } ` ) ;
69- URLParts [ 0 ] = lang ;
70- } else if ( isValidLocaleUrlException ( URLParts [ 0 ] , { _config } ) ) {
72+ log . info ( `Replacing lang in URL ${ URLPathParts [ 0 ] } -> ${ lang } ` ) ;
73+ URLPathParts [ 0 ] = lang ;
74+ } else if ( isValidLocaleUrlException ( URLPathParts [ 0 ] , { _config } ) ) {
7175 log . info ( `Prepending clientApp to URL: ${ application } ` ) ;
72- URLParts . splice ( 0 , 0 , application ) ;
76+ URLPathParts . splice ( 0 , 0 , application ) ;
7377 isApplicationFromHeader = true ;
7478 prependedOrMovedApplication = true ;
7579 } else if ( ! hasValidLang ) {
7680 // If lang wasn't valid or was missing prepend one.
7781 log . info ( `Prepending lang to URL: ${ lang } ` ) ;
78- URLParts . splice ( 0 , 0 , lang ) ;
82+ URLPathParts . splice ( 0 , 0 , lang ) ;
7983 // If we've prepended the lang to the URL we need to re-check our
8084 // URL exception and make sure it's valid.
81- hasValidClientAppUrlException = isValidClientAppUrlException ( URLParts [ 1 ] , {
82- _config,
83- } ) ;
85+ hasValidClientAppUrlException = isValidClientAppUrlException (
86+ URLPathParts [ 1 ] ,
87+ {
88+ _config,
89+ } ,
90+ ) ;
8491 }
8592
86- if ( ! hasValidClientApp && isValidClientApp ( URLParts [ 1 ] , { _config } ) ) {
93+ if ( ! hasValidClientApp && isValidClientApp ( URLPathParts [ 1 ] , { _config } ) ) {
8794 // We skip prepending an app if we'd previously prepended a lang and the
8895 // 2nd part of the URL is now a valid app.
8996 log . info ( 'Application in URL is valid following prepending a lang.' ) ;
@@ -93,7 +100,7 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
93100 ) ;
94101 } else if ( hasValidLocaleException || hasValidClientAppUrlException ) {
95102 if (
96- clientAppRoutes . includes ( URLParts [ 1 ] ) === false &&
103+ clientAppRoutes . includes ( URLPathParts [ 1 ] ) === false &&
97104 ( hasValidLang || hasValidLocaleException )
98105 ) {
99106 log . info ( 'Exception in URL found; we fallback to addons-server.' ) ;
@@ -107,14 +114,16 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
107114 } else if ( ! hasValidClientApp ) {
108115 // If the app supplied is not valid we need to prepend one.
109116 log . info ( `Prepending application to URL: ${ application } ` ) ;
110- URLParts . splice ( 1 , 0 , application ) ;
117+ URLPathParts . splice ( 1 , 0 , application ) ;
111118 isApplicationFromHeader = true ;
112119 }
113120
114121 // Redirect to the new URL.
115122 // For safety we'll deny a redirect to a URL starting with '//' since
116123 // that will be treated as a protocol-free URL.
117- const newURL = `/${ URLParts . join ( '/' ) } ` ;
124+ URLParts [ 0 ] = `/${ URLPathParts . join ( '/' ) } ` ;
125+ const newURL = URLParts . join ( '?' ) ;
126+
118127 if ( newURL !== req . originalUrl && ! newURL . startsWith ( '//' ) ) {
119128 // Collect vary headers to apply to the redirect
120129 // so we can make it cacheable.
@@ -130,7 +139,7 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
130139
131140 // Add the data to res.locals to be utilised later.
132141 /* eslint-disable no-param-reassign */
133- const [ newLang , newApp ] = URLParts ;
142+ const [ newLang , newApp ] = URLPathParts ;
134143 res . locals . lang = newLang ;
135144 // The newApp part of the URL might not be a client application
136145 // so it's important to re-check that here before assuming it's good.
0 commit comments