@@ -11,12 +11,14 @@ import { getLanguage, isValidLang } from 'core/i18n/utils';
11
11
import log from 'core/logger' ;
12
12
13
13
export function prefixMiddleware ( req , res , next , { _config = config } = { } ) {
14
+ const URLParts = req . originalUrl . split ( '?' ) ;
15
+
14
16
// Split on slashes after removing the leading slash.
15
- const URLParts = req . originalUrl . replace ( / ^ \/ / , '' ) . split ( '/' ) ;
17
+ const URLPathParts = URLParts [ 0 ] . replace ( / ^ \/ / , '' ) . split ( '/' ) ;
16
18
17
19
// Get lang and app parts from the URL. At this stage they may be incorrect
18
20
// or missing.
19
- const [ langFromURL , appFromURL ] = URLParts ;
21
+ const [ langFromURL , appFromURL ] = URLPathParts ;
20
22
21
23
// Get language from URL or fall-back to detecting it from accept-language
22
24
// header.
@@ -45,14 +47,16 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
45
47
let prependedOrMovedApplication = false ;
46
48
47
49
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
+ } );
49
53
make sure the clientApp is valid` ) ;
50
54
51
55
// Normally we look for a clientApp in the second part of a URL, but URLs
52
56
// that match a locale exception don't have a locale so we look for the
53
57
// clientApp in the first part of the URL.
54
58
if ( ! isValidClientApp ( langFromURL , { _config } ) ) {
55
- URLParts [ 0 ] = application ;
59
+ URLPathParts [ 0 ] = application ;
56
60
isApplicationFromHeader = true ;
57
61
prependedOrMovedApplication = true ;
58
62
}
@@ -65,25 +69,28 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
65
69
// * It's valid and we've mapped it e.g: pt -> pt-PT.
66
70
// * The lang is invalid but we have a valid application
67
71
// 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 } ) ) {
71
75
log . info ( `Prepending clientApp to URL: ${ application } ` ) ;
72
- URLParts . splice ( 0 , 0 , application ) ;
76
+ URLPathParts . splice ( 0 , 0 , application ) ;
73
77
isApplicationFromHeader = true ;
74
78
prependedOrMovedApplication = true ;
75
79
} else if ( ! hasValidLang ) {
76
80
// If lang wasn't valid or was missing prepend one.
77
81
log . info ( `Prepending lang to URL: ${ lang } ` ) ;
78
- URLParts . splice ( 0 , 0 , lang ) ;
82
+ URLPathParts . splice ( 0 , 0 , lang ) ;
79
83
// If we've prepended the lang to the URL we need to re-check our
80
84
// 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
+ ) ;
84
91
}
85
92
86
- if ( ! hasValidClientApp && isValidClientApp ( URLParts [ 1 ] , { _config } ) ) {
93
+ if ( ! hasValidClientApp && isValidClientApp ( URLPathParts [ 1 ] , { _config } ) ) {
87
94
// We skip prepending an app if we'd previously prepended a lang and the
88
95
// 2nd part of the URL is now a valid app.
89
96
log . info ( 'Application in URL is valid following prepending a lang.' ) ;
@@ -93,7 +100,7 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
93
100
) ;
94
101
} else if ( hasValidLocaleException || hasValidClientAppUrlException ) {
95
102
if (
96
- clientAppRoutes . includes ( URLParts [ 1 ] ) === false &&
103
+ clientAppRoutes . includes ( URLPathParts [ 1 ] ) === false &&
97
104
( hasValidLang || hasValidLocaleException )
98
105
) {
99
106
log . info ( 'Exception in URL found; we fallback to addons-server.' ) ;
@@ -107,14 +114,16 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
107
114
} else if ( ! hasValidClientApp ) {
108
115
// If the app supplied is not valid we need to prepend one.
109
116
log . info ( `Prepending application to URL: ${ application } ` ) ;
110
- URLParts . splice ( 1 , 0 , application ) ;
117
+ URLPathParts . splice ( 1 , 0 , application ) ;
111
118
isApplicationFromHeader = true ;
112
119
}
113
120
114
121
// Redirect to the new URL.
115
122
// For safety we'll deny a redirect to a URL starting with '//' since
116
123
// 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
+
118
127
if ( newURL !== req . originalUrl && ! newURL . startsWith ( '//' ) ) {
119
128
// Collect vary headers to apply to the redirect
120
129
// so we can make it cacheable.
@@ -130,7 +139,7 @@ export function prefixMiddleware(req, res, next, { _config = config } = {}) {
130
139
131
140
// Add the data to res.locals to be utilised later.
132
141
/* eslint-disable no-param-reassign */
133
- const [ newLang , newApp ] = URLParts ;
142
+ const [ newLang , newApp ] = URLPathParts ;
134
143
res . locals . lang = newLang ;
135
144
// The newApp part of the URL might not be a client application
136
145
// so it's important to re-check that here before assuming it's good.
0 commit comments