@@ -211,7 +211,7 @@ class AccountManager {
211211 }
212212
213213 public getApp ( appName : string ) : Promise < App > {
214- return this . get ( urlEncode `/apps/${ appName } ` )
214+ return this . get ( urlEncode `/apps/${ this . appNameParam ( appName ) } ` )
215215 . then ( ( res : JsonResponse ) => res . body . app ) ;
216216 }
217217
@@ -227,75 +227,75 @@ class AccountManager {
227227 }
228228
229229 public removeApp ( appName : string ) : Promise < void > {
230- return this . del ( urlEncode `/apps/${ appName } ` )
230+ return this . del ( urlEncode `/apps/${ this . appNameParam ( appName ) } ` )
231231 . then ( ( ) => null ) ;
232232 }
233233
234234 public renameApp ( oldAppName : string , newAppName : string ) : Promise < void > {
235- return this . patch ( urlEncode `/apps/${ oldAppName } ` , JSON . stringify ( { name : newAppName } ) )
235+ return this . patch ( urlEncode `/apps/${ this . appNameParam ( oldAppName ) } ` , JSON . stringify ( { name : newAppName } ) )
236236 . then ( ( ) => null ) ;
237237 }
238238
239239 public transferApp ( appName : string , email : string ) : Promise < void > {
240- return this . post ( urlEncode `/apps/${ appName } /transfer/${ email } ` , /*requestBody=*/ null , /*expectResponseBody=*/ false )
240+ return this . post ( urlEncode `/apps/${ this . appNameParam ( appName ) } /transfer/${ email } ` , /*requestBody=*/ null , /*expectResponseBody=*/ false )
241241 . then ( ( ) => null ) ;
242242 }
243243
244244 // Collaborators
245245 public getCollaborators ( appName : string ) : Promise < CollaboratorMap > {
246- return this . get ( urlEncode `/apps/${ appName } /collaborators` )
246+ return this . get ( urlEncode `/apps/${ this . appNameParam ( appName ) } /collaborators` )
247247 . then ( ( res : JsonResponse ) => res . body . collaborators ) ;
248248 }
249249
250250 public addCollaborator ( appName : string , email : string ) : Promise < void > {
251- return this . post ( urlEncode `/apps/${ appName } /collaborators/${ email } ` , /*requestBody=*/ null , /*expectResponseBody=*/ false )
251+ return this . post ( urlEncode `/apps/${ this . appNameParam ( appName ) } /collaborators/${ email } ` , /*requestBody=*/ null , /*expectResponseBody=*/ false )
252252 . then ( ( ) => null ) ;
253253 }
254254
255255 public removeCollaborator ( appName : string , email : string ) : Promise < void > {
256- return this . del ( urlEncode `/apps/${ appName } /collaborators/${ email } ` )
256+ return this . del ( urlEncode `/apps/${ this . appNameParam ( appName ) } /collaborators/${ email } ` )
257257 . then ( ( ) => null ) ;
258258 }
259259
260260 // Deployments
261261 public addDeployment ( appName : string , deploymentName : string ) : Promise < Deployment > {
262262 var deployment = < Deployment > { name : deploymentName } ;
263- return this . post ( urlEncode `/apps/${ appName } /deployments/` , JSON . stringify ( deployment ) , /*expectResponseBody=*/ true )
263+ return this . post ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/` , JSON . stringify ( deployment ) , /*expectResponseBody=*/ true )
264264 . then ( ( res : JsonResponse ) => res . body . deployment ) ;
265265 }
266266
267267 public clearDeploymentHistory ( appName : string , deploymentName : string ) : Promise < void > {
268- return this . del ( urlEncode `/apps/${ appName } /deployments/${ deploymentName } /history` )
268+ return this . del ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ deploymentName } /history` )
269269 . then ( ( ) => null ) ;
270270 }
271271
272272 public getDeployments ( appName : string ) : Promise < Deployment [ ] > {
273- return this . get ( urlEncode `/apps/${ appName } /deployments/` )
273+ return this . get ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/` )
274274 . then ( ( res : JsonResponse ) => res . body . deployments ) ;
275275 }
276276
277277 public getDeployment ( appName : string , deploymentName : string ) : Promise < Deployment > {
278- return this . get ( urlEncode `/apps/${ appName } /deployments/${ deploymentName } ` )
278+ return this . get ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ deploymentName } ` )
279279 . then ( ( res : JsonResponse ) => res . body . deployment ) ;
280280 }
281281
282282 public renameDeployment ( appName : string , oldDeploymentName : string , newDeploymentName : string ) : Promise < void > {
283- return this . patch ( urlEncode `/apps/${ appName } /deployments/${ oldDeploymentName } ` , JSON . stringify ( { name : newDeploymentName } ) )
283+ return this . patch ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ oldDeploymentName } ` , JSON . stringify ( { name : newDeploymentName } ) )
284284 . then ( ( ) => null ) ;
285285 }
286286
287287 public removeDeployment ( appName : string , deploymentName : string ) : Promise < void > {
288- return this . del ( urlEncode `/apps/${ appName } /deployments/${ deploymentName } ` )
288+ return this . del ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ deploymentName } ` )
289289 . then ( ( ) => null ) ;
290290 }
291291
292292 public getDeploymentMetrics ( appName : string , deploymentName : string ) : Promise < DeploymentMetrics > {
293- return this . get ( urlEncode `/apps/${ appName } /deployments/${ deploymentName } /metrics` )
293+ return this . get ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ deploymentName } /metrics` )
294294 . then ( ( res : JsonResponse ) => res . body . metrics ) ;
295295 }
296296
297297 public getDeploymentHistory ( appName : string , deploymentName : string ) : Promise < Package [ ] > {
298- return this . get ( urlEncode `/apps/${ appName } /deployments/${ deploymentName } /history` )
298+ return this . get ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ deploymentName } /history` )
299299 . then ( ( res : JsonResponse ) => res . body . history ) ;
300300 }
301301
@@ -304,7 +304,7 @@ class AccountManager {
304304 return Promise < void > ( ( resolve , reject , notify ) => {
305305
306306 updateMetadata . appVersion = targetBinaryVersion ;
307- var request : superagent . Request < any > = superagent . post ( this . _serverUrl + urlEncode `/apps/${ appName } /deployments/${ deploymentName } /release` ) ;
307+ var request : superagent . Request < any > = superagent . post ( this . _serverUrl + urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ deploymentName } /release` ) ;
308308 if ( this . _proxy ) ( < any > request ) . proxy ( this . _proxy ) ;
309309 this . attachCredentials ( request ) ;
310310
@@ -353,18 +353,18 @@ class AccountManager {
353353 public patchRelease ( appName : string , deploymentName : string , label : string , updateMetadata : PackageInfo ) : Promise < void > {
354354 updateMetadata . label = label ;
355355 var requestBody : string = JSON . stringify ( { packageInfo : updateMetadata } ) ;
356- return this . patch ( urlEncode `/apps/${ appName } /deployments/${ deploymentName } /release` , requestBody , /*expectResponseBody=*/ false )
356+ return this . patch ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ deploymentName } /release` , requestBody , /*expectResponseBody=*/ false )
357357 . then ( ( ) => null ) ;
358358 }
359359
360360 public promote ( appName : string , sourceDeploymentName : string , destinationDeploymentName : string , updateMetadata : PackageInfo ) : Promise < void > {
361361 var requestBody : string = JSON . stringify ( { packageInfo : updateMetadata } ) ;
362- return this . post ( urlEncode `/apps/${ appName } /deployments/${ sourceDeploymentName } /promote/${ destinationDeploymentName } ` , requestBody , /*expectResponseBody=*/ false )
362+ return this . post ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ sourceDeploymentName } /promote/${ destinationDeploymentName } ` , requestBody , /*expectResponseBody=*/ false )
363363 . then ( ( ) => null ) ;
364364 }
365365
366366 public rollback ( appName : string , deploymentName : string , targetRelease ?: string ) : Promise < void > {
367- return this . post ( urlEncode `/apps/${ appName } /deployments/${ deploymentName } /rollback/${ targetRelease || `` } ` , /*requestBody=*/ null , /*expectResponseBody=*/ false )
367+ return this . post ( urlEncode `/apps/${ this . appNameParam ( appName ) } /deployments/${ deploymentName } /rollback/${ targetRelease || `` } ` , /*requestBody=*/ null , /*expectResponseBody=*/ false )
368368 . then ( ( ) => null ) ;
369369 }
370370
@@ -516,6 +516,21 @@ class AccountManager {
516516 request . set ( "Authorization" , `Bearer ${ this . _accessKey } ` ) ;
517517 request . set ( "X-CodePush-SDK-Version" , packageJson . version ) ;
518518 }
519+
520+ // IIS and Azure web apps have this annoying behavior where %2F (URL encoded slashes) in the URL are URL decoded
521+ // BEFORE the requests reach node. That essentially means there's no good way to encode a "/" in the app name--
522+ // URL encodeing will work when running locally but when running on Azure it gets decoded before express sees it,
523+ // so app names with slashes don't get routed properly. See https://github.com/tjanczuk/iisnode/issues/343 (or other sites
524+ // that complain about the same) for some more info. I explored some IIS config based workarounds, but the previous
525+ // link seems to say they won't work, so I eventually gave up on that.
526+ // Anyway, to workaround this issue, we now allow the client to encode / characters as ~~ (two tildes, URL encoded).
527+ // The CLI now converts / to ~~ if / appears in an app name, before passing that as part of the URL. This code below
528+ // does the encoding. It's hack, but seems like the least bad option here.
529+ // Eventually, this service will go away & we'll all be on Max's new service. That's hosted in docker, no more IIS,
530+ // so this issue should go away then.
531+ private appNameParam ( appName : string ) {
532+ return appName . replace ( "/" , "~~" ) ;
533+ }
519534}
520535
521536export = AccountManager ;
0 commit comments