@@ -75,8 +75,7 @@ function updateRules(settings, tokens) {
75
75
76
76
function updateRedirects ( firebaseRef , settings ) {
77
77
return _when . promise ( function ( resolve , reject , notify ) {
78
- var redirects = settings . redirects || null ;
79
- firebaseRef . child ( 'hosting/path-redirects' ) . child ( settings . firebase ) . set ( redirects , function ( err ) {
78
+ firebaseRef . child ( 'hosting/path-redirects' ) . child ( settings . firebase ) . set ( settings . redirects , function ( err ) {
80
79
if ( err ) {
81
80
console . log ( chalk . red ( 'Settings Error' ) + ' - Incorrectly formatted "redirects" entry in the firebase.json' ) ;
82
81
process . exit ( 1 ) ;
@@ -88,8 +87,7 @@ function updateRedirects(firebaseRef, settings) {
88
87
89
88
function updateRewrites ( firebaseRef , settings ) {
90
89
return _when . promise ( function ( resolve , reject , notify ) {
91
- var rewrites = settings . rewrites || null ;
92
- firebaseRef . child ( 'hosting/rewrites' ) . child ( settings . firebase ) . set ( rewrites , function ( err ) {
90
+ firebaseRef . child ( 'hosting/rewrites' ) . child ( settings . firebase ) . set ( settings . rewrites , function ( err ) {
93
91
if ( err ) {
94
92
console . log ( chalk . red ( 'Settings Error' ) + ' - Incorrectly formatted "rewrites" entry in the firebase.json' ) ;
95
93
process . exit ( 1 ) ;
@@ -101,8 +99,7 @@ function updateRewrites(firebaseRef, settings) {
101
99
102
100
function updateHeaders ( firebaseRef , settings ) {
103
101
return _when . promise ( function ( resolve , reject , notify ) {
104
- var headers = settings . headers || null ;
105
- firebaseRef . child ( 'hosting/headers' ) . child ( settings . firebase ) . set ( headers , function ( err ) {
102
+ firebaseRef . child ( 'hosting/headers' ) . child ( settings . firebase ) . set ( settings . headers , function ( err ) {
106
103
if ( err ) {
107
104
console . log ( chalk . red ( 'Settings Error' ) + ' - Incorrectly formatted "headers" entry in the firebase.json' ) ;
108
105
process . exit ( 1 ) ;
@@ -112,6 +109,122 @@ function updateHeaders(firebaseRef, settings) {
112
109
} ) ;
113
110
}
114
111
112
+ function validateRedirects ( redirects ) {
113
+ var error = null ;
114
+ if ( redirects ) {
115
+ if ( ! Array . isArray ( redirects ) ) {
116
+ error = 'Redirects entry in the firebase.json must be an Array.' ;
117
+ } else {
118
+ for ( var i = 0 ; i < redirects . length ; i ++ ) {
119
+ var redirect = redirects [ i ] ;
120
+ if ( typeof redirect !== 'object' ) {
121
+ error = 'Redirect rule: ' + JSON . stringify ( redirect ) + ' Must be an object.' ;
122
+ } else if ( ! redirect . source || typeof redirect . source !== 'string' || redirect . source . length == 0 ) {
123
+ error = 'Redirect rule: ' + JSON . stringify ( redirect ) + ' Must contain a "source" attribute that\'s a non-empty string.' ;
124
+ } else if ( ! redirect . destination || typeof redirect . destination !== 'string' || redirect . destination . length == 0 ) {
125
+ error = 'Redirect rule: ' + JSON . stringify ( redirect ) + ' Must contain a "destination" attribute that\'s a non-empty string.' ;
126
+ } else if ( ! / ^ ( \/ [ ^ \s ] * | h t t p s ? : \/ \/ [ ^ \s ] + ) $ / . test ( redirect . destination ) ) {
127
+ error = 'Redirect destination: "' + redirect . destination + '" Must be a remote or absolute url and start with "http", "https", or a "/".' ;
128
+ } else if ( redirect . type !== 301 && redirect . type !== 302 ) {
129
+ error = 'Redirect rule: ' + JSON . stringify ( redirect ) + ' Must have a redirect "type" that\'s either 301 for a permanent redirect or 302 for a temporary redirect.' ;
130
+ } else if ( Object . keys ( redirect ) . length > 3 ) {
131
+ error = 'Redirect rule: ' + JSON . stringify ( redirect ) + ' Must not contain any keys other than "source", "destination", or "type".' ;
132
+ }
133
+ if ( error ) {
134
+ break ;
135
+ }
136
+ }
137
+ }
138
+ }
139
+ if ( error ) {
140
+ console . log ( chalk . red ( 'Settings Error' ) + ' - ' + error ) ;
141
+ process . exit ( 1 ) ;
142
+ }
143
+ }
144
+
145
+ function validateRewrites ( rewrites ) {
146
+ var error = null ;
147
+ if ( rewrites ) {
148
+ if ( ! Array . isArray ( rewrites ) ) {
149
+ error = 'Rewrites entry in the firebase.json must be an Array.' ;
150
+ } else {
151
+ for ( var i = 0 ; i < rewrites . length ; i ++ ) {
152
+ var rewrite = rewrites [ i ] ;
153
+ if ( typeof rewrite !== 'object' ) {
154
+ error = 'Rewrite rule: ' + JSON . stringify ( rewrite ) + ' Must be an object.' ;
155
+ } else if ( ! rewrite . source || typeof rewrite . source !== 'string' || rewrite . source . length == 0 ) {
156
+ error = 'Rewrite rule: ' + JSON . stringify ( rewrite ) + ' Must contain a "source" attribute that\'s a non-empty string.' ;
157
+ } else if ( ! rewrite . destination || typeof rewrite . destination !== 'string' || rewrite . destination . length == 0 ) {
158
+ error = 'Rewrite rule: ' + JSON . stringify ( rewrite ) + ' Must contain a "destination" attribute that\'s a non-empty string.' ;
159
+ } else if ( ! / ^ \/ [ ^ \s ] * [ ^ \/ \s ] $ / . test ( rewrite . destination ) ) {
160
+ error = 'Rewrite destination: "' + rewrite . destination + '" Must be an absolute path to a file that starts with a "/" and does not end in a "/".' ;
161
+ } else if ( Object . keys ( rewrite ) . length > 2 ) {
162
+ error = 'Rewrite rule: ' + JSON . stringify ( rewrite ) + ' Must not contain any keys other than "source" or "destination".' ;
163
+ }
164
+ if ( error ) {
165
+ break ;
166
+ }
167
+ }
168
+ }
169
+ }
170
+ if ( error ) {
171
+ console . log ( chalk . red ( 'Settings Error' ) + ' - ' + error ) ;
172
+ process . exit ( 1 ) ;
173
+ }
174
+ }
175
+
176
+ function validateHeaders ( headers ) {
177
+ var error = null ,
178
+ supportedHeaders = [
179
+ 'Access-Control-Allow-Origin' ,
180
+ 'Cache-Control'
181
+ ] ;
182
+ if ( headers ) {
183
+ if ( ! Array . isArray ( headers ) ) {
184
+ error = 'Headers entry in the firebase.json must be an Array.' ;
185
+ } else {
186
+ for ( var i = 0 ; i < headers . length ; i ++ ) {
187
+ var header = headers [ i ] ;
188
+ if ( typeof header !== 'object' ) {
189
+ error = 'Header rule: ' + JSON . stringify ( header ) + ' Must be an object.' ;
190
+ } else if ( ! header . source || typeof header . source !== 'string' || header . source . length === 0 ) {
191
+ error = 'Header rule: ' + JSON . stringify ( header ) + ' Must contain a "source" attribute that\'s a non-empty string.' ;
192
+ } else if ( ! header . headers || ! Array . isArray ( header . headers ) ) {
193
+ error = 'Header rule: ' + JSON . stringify ( header ) + ' Must contain a "headers" attribute that\'s an array.' ;
194
+ } else if ( Object . keys ( header ) . length > 2 ) {
195
+ error = 'Header rule: ' + JSON . stringify ( header ) + ' Must not contain any keys other than "source" or "headers".' ;
196
+ }
197
+ if ( ! error ) {
198
+ for ( var j = 0 ; j < header . headers . length ; j ++ ) {
199
+ var individualHeader = header . headers [ j ] ;
200
+ if ( typeof individualHeader !== 'object' ) {
201
+ error = 'Header: ' + JSON . stringify ( individualHeader ) + ' Must be an object' ;
202
+ } else if ( ! individualHeader [ 'key' ] || typeof individualHeader [ 'key' ] !== 'string' || individualHeader [ 'key' ] . length === 0 ) {
203
+ error = 'Header: ' + JSON . stringify ( individualHeader ) + ' Must contain a "key" field that\'s one of: "' + supportedHeaders . join ( '", "' ) + '"' ;
204
+ } else if ( ! individualHeader [ 'value' ] || typeof individualHeader [ 'value' ] !== 'string' || individualHeader [ 'value' ] . length === 0 ) {
205
+ error = 'Header: ' + JSON . stringify ( individualHeader ) + ' Must contain a "value" field that\'s a non-empty string.' ;
206
+ } else if ( supportedHeaders . indexOf ( individualHeader [ 'key' ] ) < 0 ) {
207
+ error = 'Header key: "' + individualHeader [ 'key' ] + '" is not supported. Supported keys are: "' + supportedHeaders . join ( '", "' ) + '"' ;
208
+ } else if ( Object . keys ( individualHeader ) . length > 2 ) {
209
+ error = 'Header: ' + JSON . stringify ( individualHeader ) + ' Must not contain any keys other than "key" or "value".' ;
210
+ }
211
+ if ( error ) {
212
+ break ;
213
+ }
214
+ }
215
+ }
216
+ if ( error ) {
217
+ break ;
218
+ }
219
+ }
220
+ }
221
+ }
222
+ if ( error ) {
223
+ console . log ( chalk . red ( 'Settings Error' ) + ' - ' + error ) ;
224
+ process . exit ( 1 ) ;
225
+ }
226
+ }
227
+
115
228
function uploadSite ( settings , directoryRef , argv ) {
116
229
return function ( ) {
117
230
var bar = null ;
@@ -520,6 +633,13 @@ module.exports = {
520
633
process . exit ( 1 ) ;
521
634
}
522
635
636
+ settings . rewrites = settings . rewrites || null ;
637
+ validateRewrites ( settings . rewrites ) ;
638
+ settings . redirects = settings . redirects || null ;
639
+ validateRedirects ( settings . redirects ) ;
640
+ settings . headers = settings . headers || null ;
641
+ validateHeaders ( settings . headers ) ;
642
+
523
643
var firebaseRef = new Firebase ( api . realtimeUrl . replace ( / \/ \/ / , '//firebase.' ) ) ;
524
644
firebaseRef . auth ( tokens . firebaseToken , function ( error , result ) {
525
645
if ( error ) {
0 commit comments