Forráskód Böngészése

Refactor `APICaller` to use the 'axios' library

'axios' is a `Promise` based library that wraps around `XMLHttpRequest` on Javascript and `http` on Node.
'axios' also simplifies error and server status handling.
Sergiu Miclea 8 éve
szülő
commit
0b445cd8c1

+ 1 - 0
package.json

@@ -55,6 +55,7 @@
   "dependencies": {
     "@webpack-blocks/webpack2": "^0.4.0",
     "ajax-request": "^1.2.3",
+    "axios": "^0.18.0",
     "babel-core": "^6.26.0",
     "babel-loader": "^7.1.2",
     "babel-plugin-styled-components": "^1.2.1",

+ 1 - 1
src/sources/AssessmentSource.js

@@ -61,7 +61,7 @@ class AssessmentSource {
         }
       })
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/${type}s`,
         method: 'POST',
         data: payload,

+ 36 - 42
src/sources/EndpointSource.js

@@ -42,10 +42,7 @@ class EdnpointSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
       if (projectId) {
-        Api.sendAjaxRequest({
-          url: `${servicesUrl.coriolis}/${projectId}/endpoints`,
-          method: 'GET',
-        }).then(response => {
+        Api.get(`${servicesUrl.coriolis}/${projectId}/endpoints`).then(response => {
           let connections = []
           if (response.data.endpoints.length) {
             response.data.endpoints.forEach(endpoint => {
@@ -56,7 +53,7 @@ class EdnpointSource {
           connections.sort((c1, c2) => moment(c2.created_at).diff(moment(c1.created_at)))
 
           resolve(connections)
-        }, reject).catch(reject)
+        }).catch(reject)
       } else {
         reject()
       }
@@ -66,7 +63,7 @@ class EdnpointSource {
     return new Promise((resolve, reject) => {
       let projectId :any = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId}/endpoints/${endpoint.id}`,
         method: 'DELETE',
       }).then(() => {
@@ -74,14 +71,14 @@ class EdnpointSource {
           let uuidIndex = endpoint.connection_info.secret_ref.lastIndexOf('/')
           // $FlowIssue
           let uuid = endpoint.connection_info.secret_ref.substr(uuidIndex + 1)
-          Api.sendAjaxRequest({
+          Api.send({
             url: `${servicesUrl.barbican}/v1/secrets/${uuid}`,
             method: 'DELETE',
-          }).then(() => { resolve(endpoint.id) }, reject).catch(reject)
+          }).then(() => { resolve(endpoint.id) }).catch(reject)
         } else {
           resolve(endpoint.id)
         }
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -90,14 +87,13 @@ class EdnpointSource {
     let uuid = index && endpoint.connection_info.secret_ref && endpoint.connection_info.secret_ref.substr(index + 1)
 
     return new Promise((resolve, reject) => {
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.barbican}/v1/secrets/${uuid || ''}/payload`,
-        method: 'GET',
-        json: false,
+        responseType: 'text',
         headers: { Accept: 'text/plain' },
       }).then((response) => {
-        resolve(JSON.parse(response.data))
-      }, reject).catch(reject)
+        resolve(response.data)
+      }).catch(reject)
     })
   }
 
@@ -120,13 +116,12 @@ class EdnpointSource {
       endpoints.forEach(endpoint => {
         let index = endpoint.connection_info.secret_ref ? endpoint.connection_info.secret_ref.lastIndexOf('/') : ''
         let uuid = endpoint.connection_info.secret_ref && index ? endpoint.connection_info.secret_ref.substr(index + 1) : ''
-        Api.sendAjaxRequest({
+        Api.send({
           url: `${servicesUrl.barbican}/v1/secrets/${uuid}/payload`,
-          method: 'GET',
-          json: false,
+          responseType: 'text',
           headers: { Accept: 'text/plain' },
         }).then(response => {
-          connectionsInfo.push({ ...endpoint, connection_info: JSON.parse(response.data) })
+          connectionsInfo.push({ ...endpoint, connection_info: response.data })
           isDone()
         }, isDone).catch(isDone)
       })
@@ -136,13 +131,13 @@ class EdnpointSource {
   static validate(endpoint: Endpoint): Promise<Validation> {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || ''}/endpoints/${endpoint.id}/actions`,
         method: 'POST',
         data: { 'validate-connection': null },
       }).then(response => {
         resolve(response.data['validate-connection'])
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -157,12 +152,12 @@ class EdnpointSource {
         // $FlowIgnore
         let uuid = parsedEndpoint.connection_info.secret_ref.substr(uuidIndex + 1)
 
-        Api.sendAjaxRequest({
+        Api.send({
           url: `${servicesUrl.barbican}/v1/secrets/${uuid}`,
           method: 'DELETE',
         })
 
-        Api.sendAjaxRequest({
+        Api.send({
           url: `${servicesUrl.barbican}/v1/secrets`,
           method: 'POST',
           data: getBarbicanPayload(ObjectUtils.skipField(parsedEndpoint.connection_info, 'secret_ref')),
@@ -175,7 +170,7 @@ class EdnpointSource {
               connection_info: connectionInfo,
             },
           }
-          Api.sendAjaxRequest({
+          Api.send({
             url: `${servicesUrl.coriolis}/${projectId || ''}/endpoints/${endpoint.id}`,
             method: 'PUT',
             data: newPayload,
@@ -184,28 +179,28 @@ class EdnpointSource {
             uuid = connectionInfo.secret_ref.substr(uuidIndex + 1)
             let newEndpoint = putResponse.data.endpoint
 
-            Api.sendAjaxRequest({
+            Api.send({
               url: `${servicesUrl.barbican}/v1/secrets/${uuid}/payload`,
               method: 'GET',
-              json: false,
+              responseType: 'text',
               headers: { Accept: 'text/plain' },
             }).then(conInfoResponse => {
               newEndpoint.connection_info = {
                 ...newEndpoint.connection_info,
-                ...JSON.parse(conInfoResponse.data),
+                ...conInfoResponse.data,
               }
               resolve(newEndpoint)
-            }, reject).catch(reject)
-          }, reject).catch(reject)
-        }, reject).catch(reject)
+            }).catch(reject)
+          }).catch(reject)
+        }).catch(reject)
       } else {
-        Api.sendAjaxRequest({
+        Api.send({
           url: `${servicesUrl.coriolis}/${projectId || ''}/endpoints/${endpoint.id}`,
           method: 'PUT',
           data: { endpoint: parsedEndpoint },
         }).then(response => {
           resolve(response.data.endpoint)
-        }, reject).catch(reject)
+        }).catch(reject)
       }
     })
   }
@@ -215,7 +210,7 @@ class EdnpointSource {
       let parsedEndpoint = SchemaParser.fieldsToPayload(endpoint)
       let projectId = cookie.get('projectId')
       if (useSecret) {
-        Api.sendAjaxRequest({
+        Api.send({
           url: `${servicesUrl.barbican}/v1/secrets`,
           method: 'POST',
           data: getBarbicanPayload(ObjectUtils.skipField(parsedEndpoint.connection_info, 'secret_ref')),
@@ -229,7 +224,7 @@ class EdnpointSource {
               connection_info: connectionInfo,
             },
           }
-          Api.sendAjaxRequest({
+          Api.send({
             url: `${servicesUrl.coriolis}/${projectId || ''}/endpoints`,
             method: 'POST',
             data: newPayload,
@@ -238,28 +233,27 @@ class EdnpointSource {
             let uuid = connectionInfo.secret_ref.substr(uuidIndex + 1)
             let newEndpoint = postResponse.data.endpoint
 
-            Api.sendAjaxRequest({
+            Api.send({
               url: `${servicesUrl.barbican}/v1/secrets/${uuid}/payload`,
-              method: 'GET',
-              json: false,
+              responseType: 'text',
               headers: { Accept: 'text/plain' },
             }).then(conInfoResponse => {
               newEndpoint.connection_info = {
                 ...newEndpoint.connection_info,
-                ...JSON.parse(conInfoResponse.data),
+                ...conInfoResponse.data,
               }
               resolve(newEndpoint)
-            }, reject).catch(reject)
-          }, reject).catch(reject)
-        }, reject).catch(reject)
+            }).catch(reject)
+          }).catch(reject)
+        }).catch(reject)
       } else {
-        Api.sendAjaxRequest({
+        Api.send({
           url: `${servicesUrl.coriolis}/${projectId || ''}/endpoints`,
           method: 'POST',
           data: { endpoint: parsedEndpoint },
         }).then(response => {
           resolve(response.data.endpoint)
-        }, reject).catch(reject)
+        }).catch(reject)
       }
     })
   }

+ 5 - 13
src/sources/InstanceSource.js

@@ -46,14 +46,11 @@ class InstanceSource {
         url = `${url + symbol}&marker=${lastInstanceId}`
       }
 
-      Api.sendAjaxRequest({
-        url,
-        method: 'GET',
-      }).then(response => {
+      Api.get(url).then(response => {
         if (this.endpointId === endpointId) {
           resolve(response.data.instances)
         }
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -61,10 +58,9 @@ class InstanceSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId') || 'undefined'
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId}/endpoints/${endpointId}/instances/${btoa(instanceName)}`,
-        method: 'GET',
-        requestId: `instanceDetail-${reqId}}`,
+        cancelId: `instanceDetail-${reqId}`,
       }).then(response => {
         resolve({ instance: response.data.instance, reqId })
       }, response => { reject({ response, reqId }) }).catch(reject)
@@ -72,11 +68,7 @@ class InstanceSource {
   }
 
   static cancelInstancesDetailsRequests(reqId: number) {
-    Api.requests.forEach(request => {
-      if (request.requestId.indexOf(`instanceDetail-${reqId}`) > -1) {
-        Api.cancelRequest(request)
-      }
-    })
+    Api.cancelRequests(`instanceDetail-${reqId}`)
   }
 }
 

+ 9 - 15
src/sources/MigrationSource.js

@@ -53,14 +53,11 @@ class MigrationSource {
   static getMigrations(): Promise<MainItem[]> {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId') || 'null'
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId}/migrations/detail`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId}/migrations/detail`).then(response => {
         let migrations = response.data.migrations
         MigrationSourceUtils.sortMigrations(migrations)
         resolve(migrations)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -68,14 +65,11 @@ class MigrationSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId') || 'null'
 
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId}/migrations/${migrationId}`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId}/migrations/${migrationId}`).then(response => {
         let migration = response.data.migration
         MigrationSourceUtils.sortTaskUpdates(migration)
         resolve(migration)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -83,20 +77,20 @@ class MigrationSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId') || 'null'
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId}/migrations/${migrationId}/actions`,
         method: 'POST',
         data: { cancel: null },
       }).then(() => {
         resolve(migrationId)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
   static delete(migrationId: string): Promise<string> {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/migrations/${migrationId}`,
         method: 'DELETE',
       }).then(() => { resolve(migrationId) }, reject).catch(reject)
@@ -115,14 +109,14 @@ class MigrationSource {
         payload.migration[o.name] = o.value || false
       })
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/migrations`,
         method: 'POST',
         data: payload,
       }).then(response => {
         let migration = response.data.migration
         resolve(migration)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 }

+ 2 - 5
src/sources/NetworkSource.js

@@ -30,14 +30,11 @@ class NetworkSource {
         url = `${url}?env=${btoa(JSON.stringify(environment))}`
       }
 
-      Api.sendAjaxRequest({
-        url,
-        method: 'GET',
-      }).then(response => {
+      Api.get(url).then(response => {
         let networks = response.data.networks.filter(n => n.name.indexOf('coriolis-migrnet') === -1)
         networks.sort((a, b) => a.name.localeCompare(b.name))
         resolve(networks)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 }

+ 1 - 4
src/sources/ProjectSource.js

@@ -22,10 +22,7 @@ import type { Project } from '../types/Project'
 class ProjectsSource {
   static getProjects(): Promise<Project[]> {
     return new Promise((resolve, reject) => {
-      Api.sendAjaxRequest({
-        url: servicesUrl.projects,
-        method: 'GET',
-      }).then((response) => {
+      Api.get(servicesUrl.projects).then((response) => {
         if (response.data.projects) {
           resolve(response.data.projects)
         }

+ 7 - 19
src/sources/ProviderSource.js

@@ -28,14 +28,11 @@ class ProviderSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId || 'null'}/providers/${providerName}/schemas/${providerTypes.CONNECTION}`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/providers/${providerName}/schemas/${providerTypes.CONNECTION}`).then(response => {
         let schema = response.data.schemas.connection_info_schema
         schema = SchemaParser.connectionSchemaToFields(providerName, schema)
         resolve(schema)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -43,12 +40,9 @@ class ProviderSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId || 'null'}/providers`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/providers`).then(response => {
         resolve(response.data.providers)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -57,14 +51,11 @@ class ProviderSource {
       let projectId = cookie.get('projectId')
       let schemaTypeInt = schemaType === 'migration' ? providerTypes.TARGET_MIGRATION : providerTypes.TARGET_REPLICA
 
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId || 'null'}/providers/${providerName}/schemas/${schemaTypeInt}`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/providers/${providerName}/schemas/${schemaTypeInt}`).then(response => {
         let schema = response.data.schemas.destination_environment_schema
         let fields = SchemaParser.optionsSchemaToFields(providerName, schema)
         resolve(fields)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -72,10 +63,7 @@ class ProviderSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId || 'null'}/endpoints/${endpointId}/destination-options`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/endpoints/${endpointId}/destination-options`).then(response => {
         let options = response.data.destination_options
         resolve(options)
       }).catch(() => { reject() })

+ 15 - 24
src/sources/ReplicaSource.js

@@ -87,30 +87,24 @@ class ReplicaSource {
   static getReplicas(): Promise<MainItem[]> {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/detail`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/replicas/detail`).then(response => {
         let replicas = response.data.replicas
         replicas = ReplicaSourceUtils.filterDeletedExecutionsInReplicas(replicas)
         ReplicaSourceUtils.sortReplicas(replicas)
         resolve(replicas)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
   static getReplicaExecutions(replicaId: string): Promise<Execution[]> {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions/detail`,
-        method: 'GET',
-      }).then((response) => {
+      Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions/detail`).then((response) => {
         let executions = response.data.executions
         ReplicaSourceUtils.sortExecutionsAndTaskUpdates(executions)
 
         resolve(executions)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -118,15 +112,12 @@ class ReplicaSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}`).then(response => {
         let replica = response.data.replica
         replica.executions = ReplicaSourceUtils.filterDeletedExecutions(replica.executions)
         ReplicaSourceUtils.sortExecutions(replica.executions)
         resolve(replica)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -140,7 +131,7 @@ class ReplicaSource {
       }
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions`,
         method: 'POST',
         data: payload,
@@ -148,7 +139,7 @@ class ReplicaSource {
         let execution = response.data.execution
         ReplicaSourceUtils.sortTaskUpdates(execution)
         resolve(execution)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -156,13 +147,13 @@ class ReplicaSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions/${executionId}/actions`,
         method: 'POST',
         data: { cancel: null },
       }).then(() => {
         resolve(replicaId)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -170,12 +161,12 @@ class ReplicaSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions/${executionId}`,
         method: 'DELETE',
       }).then(() => {
         resolve(replicaId)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -183,7 +174,7 @@ class ReplicaSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}`,
         method: 'DELETE',
       }).then(() => { resolve(replicaId) }, reject).catch(reject)
@@ -194,13 +185,13 @@ class ReplicaSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/actions`,
         method: 'POST',
         data: { 'delete-disks': null },
       }).then(response => {
         resolve(response.data.execution)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 }

+ 10 - 13
src/sources/ScheduleSource.js

@@ -47,13 +47,13 @@ class ScheduleSource {
         })
       }
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/schedules`,
         method: 'POST',
         data: payload,
       }).then(response => {
         resolve(response.data.schedule)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -81,10 +81,7 @@ class ScheduleSource {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
 
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/schedules`,
-        method: 'GET',
-      }).then(response => {
+      Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/schedules`).then(response => {
         let schedules = [...response.data.schedules]
 
         schedules.forEach(s => {
@@ -98,7 +95,7 @@ class ScheduleSource {
         })
         schedules.sort((a, b) => moment(a.created_at).diff(b.created_at))
         resolve(schedules)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
@@ -113,23 +110,23 @@ class ScheduleSource {
         payload.schedule = { ...schedule.schedule }
       }
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/schedules`,
         method: 'POST',
         data: payload,
       }).then(response => {
         resolve(response.data.schedule)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 
   static removeSchedule(replicaId: string, scheduleId: string): Promise<void> {
     return new Promise((resolve, reject) => {
       let projectId = cookie.get('projectId')
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/schedules/${scheduleId}`,
         method: 'DELETE',
-      }).then(resolve, reject).catch(reject)
+      }).then(() => { resolve() }).catch(reject)
     })
   }
 
@@ -167,7 +164,7 @@ class ScheduleSource {
         })
       }
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/schedules/${scheduleId}`,
         method: 'PUT',
         data: payload,
@@ -180,7 +177,7 @@ class ScheduleSource {
           s.shutdown_instances = s.shutdown_instance
         }
         resolve(s)
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 }

+ 22 - 31
src/sources/UserSource.js

@@ -21,15 +21,15 @@ import { servicesUrl } from '../config'
 import type { Credentials, User } from '../types/User'
 
 class UserModel {
-  static parseUserData(response) {
-    let data = {
-      id: response.data.token.user.id,
-      name: response.data.token.user.name,
-      email: response.data.token.user.email,
-      project: response.data.token.project,
+  static parseUserData(data: any) {
+    let newData = {
+      id: data.token.user.id,
+      name: data.token.user.name,
+      email: data.token.user.email,
+      project: data.token.project,
     }
 
-    return data
+    return newData
   }
 }
 
@@ -54,16 +54,16 @@ class UserSource {
     Api.setDefaultHeader('X-Auth-Token', null)
 
     return new Promise((resolve, reject) => {
-      Api.sendAjaxRequest({
+      Api.send({
         url: servicesUrl.identity,
         method: 'POST',
         data: auth,
       }).then((response) => {
-        let token = response.headers['X-Subject-Token'] || response.headers['x-subject-token']
+        let token = response.headers ? response.headers['X-Subject-Token'] || response.headers['x-subject-token'] : ''
         Api.setDefaultHeader('X-Auth-Token', token)
         cookie.set('unscopedToken', token, { expires: 30 })
-        resolve(response)
-      }, reject).catch(reject)
+        resolve(response.data)
+      }).catch(reject)
     })
   }
 
@@ -90,13 +90,13 @@ class UserSource {
     Api.setDefaultHeader('X-Auth-Token', null)
 
     return new Promise((resolve, reject) => {
-      Api.sendAjaxRequest({
+      Api.send({
         url: servicesUrl.identity,
         method: 'POST',
         data: auth,
       }).then((response) => {
-        let token = response.headers['X-Subject-Token'] || response.headers['x-subject-token']
-        let data = UserModel.parseUserData(response)
+        let token = response.headers ? response.headers['X-Subject-Token'] || response.headers['x-subject-token'] : ''
+        let data = UserModel.parseUserData(response.data)
         data = { ...data, token }
         cookie.set('token', data.token, { expires: 30 })
         cookie.set('projectId', data.project.id, { expires: 30 })
@@ -125,23 +125,17 @@ class UserSource {
         reject()
         return
       }
-      Api.sendAjaxRequest({
+      Api.send({
         url: servicesUrl.identity,
-        method: 'GET',
         headers: { 'X-Subject-Token': token },
       }).then(response => {
-        let data = UserModel.parseUserData(response)
+        let data = UserModel.parseUserData(response.data)
         data = { ...data, token }
         resolve(data)
-      }, () => {
-        cookie.remove('token')
-        cookie.remove('projectId')
-        Api.resetHeaders()
-        reject()
       }).catch(() => {
         cookie.remove('token')
         cookie.remove('projectId')
-        Api.resetHeaders()
+        Api.setDefaultHeader('X-Auth-Token', null)
         reject()
       })
     })
@@ -163,30 +157,27 @@ class UserSource {
     let token = cookie.get('token')
 
     return new Promise((resolve, reject) => {
-      Api.sendAjaxRequest({
+      Api.send({
         url: servicesUrl.identity,
         method: 'DELETE',
-        headers: { 'X-Subject-Token': token },
+        headers: { 'X-Subject-Token': token || '' },
       }).then(() => {
         cookie.remove('token')
         window.location.href = '/'
         resolve()
-      }, reject).catch(() => {
+      }).catch(() => {
         cookie.remove('token')
         window.location.href = '/'
         reject()
       })
 
-      Api.resetHeaders()
+      Api.setDefaultHeader('X-Auth-Token', null)
     })
   }
 
   static getUserInfo(user: User): Promise<User> {
     return new Promise((resolve, reject) => {
-      Api.sendAjaxRequest({
-        url: `${servicesUrl.users}/${user.id}`,
-        method: 'GET',
-      }).then((response) => {
+      Api.get(`${servicesUrl.users}/${user.id}`).then((response) => {
         resolve(response.data.user)
       }, reject).catch(reject)
     })

+ 2 - 2
src/sources/WizardSource.js

@@ -68,13 +68,13 @@ class WizardSource {
         payload[type].skip_os_morphing = data.options.skip_os_morphing
       }
 
-      Api.sendAjaxRequest({
+      Api.send({
         url: `${servicesUrl.coriolis}/${projectId || 'null'}/${type}s`,
         method: 'POST',
         data: payload,
       }).then(response => {
         resolve(response.data[type])
-      }, reject).catch(reject)
+      }).catch(reject)
     })
   }
 

+ 74 - 127
src/utils/ApiCaller.js

@@ -14,167 +14,114 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 // @flow
 
-import NotificationStore from '../stores/NotificationStore'
-
-let apiInstance = null
+import axios from 'axios'
+import type { AxiosXHRConfig, $AxiosXHR } from 'axios'
 
-type RequestOptions = {
-  method: string,
-  url: string,
-  requestId?: string,
-  headers?: {[string]: mixed},
-}
+import NotificationStore from '../stores/NotificationStore'
 
-type RequestInfo = {
+type Cancelable = {
   requestId: string,
-  request: XMLHttpRequest,
+  cancel: () => void,
 }
 
-class ApiCaller {
-  defaultHeaders = {
-    'Content-Type': 'application/json',
+type RequestOptions = {|
+  url: string,
+  method?: string,
+  cancelId?: string,
+  headers?: {[string]: string},
+  data?: any,
+  responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream',
+|}
+
+let cancelables: Cancelable[] = []
+const CancelToken = axios.CancelToken
+
+const addCancelable = (cancelable: Cancelable) => {
+  cancelables.unshift(cancelable)
+  if (cancelables.length > 100) {
+    cancelables.pop()
   }
+}
 
-  requests = []
-
+class ApiCaller {
   constructor() {
-    if (!apiInstance) {
-      apiInstance = this
-    }
-
-    return apiInstance
+    axios.defaults.headers.common['Content-Type'] = 'application/json'
   }
 
-  addRequest(requestInfo: RequestInfo) {
-    this.requests.unshift(requestInfo)
-    if (this.requests.length > 100) {
-      this.requests.pop()
-    }
+  cancelRequests(cancelRequestId: string) {
+    const filteredCancelables = cancelables.filter(r => r.requestId === cancelRequestId)
+    filteredCancelables.forEach(c => {
+      c.cancel()
+    })
+    cancelables = cancelables.filter(r => r.requestId !== cancelRequestId)
   }
 
-  cancelRequest(requestInfo: RequestInfo) {
-    requestInfo.request.abort()
-    this.requests = this.requests.filter(r => r.requestId !== requestInfo.requestId)
+  get(url: string): Promise<$AxiosXHR<any>> {
+    return this.send({ url })
   }
 
-  sendAjaxRequest(options: RequestOptions): Promise<any> {
+  send(options: RequestOptions): Promise<$AxiosXHR<any>> {
     return new Promise((resolve, reject) => {
-      let request = new XMLHttpRequest()
-
-      if (options.requestId) {
-        this.addRequest({ requestId: options.requestId, request })
+      const axiosOptions: AxiosXHRConfig<any> = {
+        url: options.url,
+        method: options.method || 'GET',
+        headers: options.headers || {},
+        data: options.data || null,
+        responseType: options.responseType || 'json',
       }
 
-      request.open(options.method, options.url)
-
-      let headers = Object.assign({}, this.defaultHeaders)
-
-      if (options.headers) {
-        Object.keys(options.headers).forEach((key) => {
-          headers[key] = options.headers ? options.headers[key] : ''
+      if (options.cancelId) {
+        let cancel = () => {}
+        axiosOptions.cancelToken = new CancelToken(c => {
+          cancel = c
         })
+        addCancelable({ requestId: options.cancelId, cancel })
       }
 
-      Object.keys(headers).forEach((name) => {
-        request.setRequestHeader(name, headers[name])
-      })
-
-      request.onreadystatechange = () => {
-        if (request.readyState === 4) { // if complete
-          if (!(request.status >= 200 && request.status <= 299)) { // check if "OK" (200)
-            reject({ status: request.status })
-          } else if (request.status === 0) { // check if aborted
-            reject({ status: 0 })
-          }
-        }
-      }
+      console.log(`%cSending ${axiosOptions.method || 'GET'} Request to ${axiosOptions.url}`, 'color: #F5A623')
 
-      console.log(`%cSending ${options.method} Request to ${options.url}`, 'color: #F5A623') // eslint-disable-line no-console
+      axios(axiosOptions).then((response) => {
+        console.log(`%cResponse ${axiosOptions.url}`, 'color: #0044CA', response.data)
+        resolve(response)
+      }).catch(error => {
+        const loginUrl = '#/'
 
-      try {
-        options.data ? request.send(JSON.stringify(options.data)) : request.send()
-      } catch (err) {
-        reject(err)
-      }
-
-      request.onload = () => {
-        let data = null
+        if (error.response) {
+          // The request was made and the server responded with a status code
+          // that falls out of the range of 2xx
+          if (error.response.status !== 401 || window.location.hash !== loginUrl) {
+            NotificationStore.notify(error.response.data.error.message, 'error')
+          }
 
-        if (options.json !== false && request.responseText) {
-          try {
-            data = JSON.parse(request.responseText)
-          } catch (err) {
-            reject({ message: 'Invalid server response!' })
+          if (error.response.status === 401 && window.location.hash !== loginUrl) {
+            window.location.href = `/${loginUrl}`
           }
-        } else if (request.responseText) {
-          data = request.responseText
-        }
 
-        let result = {
-          status: request.status,
-          data,
-          headers: ApiCaller.processHeaders(request.getAllResponseHeaders()),
-        }
-        if (result.status >= 200 && result.status <= 299) {
-          console.log(`%cResponse ${options.url}`, 'color: #0044CA', result.data) // eslint-disable-line no-console
-          resolve(result)
+          console.log(`%cError Response: ${axiosOptions.url}`, 'color: #D0021B', error.response)
+          reject(error.response)
+        } else if (error.request) {
+          // The request was made but no response was received
+          // `error.request` is an instance of XMLHttpRequest
+          NotificationStore.notify('Request failed, there might be a problem with the connection to the server.', 'error')
+          console.log(`%cError No Response: ${axiosOptions.url}`, 'color: #D0021B')
+          reject({})
         } else {
-          console.log(`%cError Response: ${options.url}`, 'color: #D0021B', result.data) // eslint-disable-line no-console
+          reject({})
 
-          let loginUrl = '#/'
-
-          if (result.data && result.data.error && result.data.error.message &&
-            (result.status !== 401 || window.location.hash !== loginUrl)) {
-            // $FlowIgnore
-            NotificationStore.notify(result.data.error.message, 'error')
+          if (error.constructor.name === 'Cancel') {
+            return
           }
 
-          if (result.status === 401 && window.location.hash !== loginUrl) {
-            this.resetHeaders()
-            window.location.href = `/${loginUrl}`
-          }
-          reject({ status: request.status })
-        }
-      }
-
-      request.onerror = (result) => {
-        let loginUrl = '#/'
-        if (window.location.hash !== loginUrl) {
-          NotificationStore.notify(`Request failed, there might be a problem with the 
-          connection to the server.`, 'error')
+          // Something happened in setting up the request that triggered an Error
+          NotificationStore.notify('Request failed, there might be a problem with the connection to the server.', 'error')
+          console.log(`%cError Something happened in setting up the request: ${axiosOptions.url}`, 'color: #D0021B')
         }
-
-        // $FlowIgnore
-        console.log('%cError Response: ', 'color: #D0021B', result.data) // eslint-disable-line no-console
-        reject({ status: 500, data: 'Connection error' })
-      }
-    })
-  }
-
-  resetHeaders() {
-    this.defaultHeaders = {
-      'Content-Type': 'application/json',
-    }
-  }
-
-  static processHeaders(rawHeaders: string) {
-    let headers = {}
-    let lines = rawHeaders.split('\n')
-    lines.forEach((line) => {
-      let comps = line.split(':')
-      if (comps[0].length) {
-        headers[comps[0]] = comps[1].trim()
-      }
+      })
     })
-    return headers
   }
 
   setDefaultHeader(name: string, value: ?string) {
-    if (value == null) {
-      delete this.defaultHeaders[name]
-    } else {
-      this.defaultHeaders[name] = value
-    }
+    axios.defaults.headers.common[name] = value
   }
 }
 

+ 13 - 0
yarn.lock

@@ -552,6 +552,13 @@ aws4@^1.2.1, aws4@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
 
+axios@^0.18.0:
+  version "0.18.0"
+  resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
+  dependencies:
+    follow-redirects "^1.3.0"
+    is-buffer "^1.1.5"
+
 axobject-query@^0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-0.1.0.tgz#62f59dbc59c9f9242759ca349960e7a2fe3c36c0"
@@ -3406,6 +3413,12 @@ flow-typed@^2.3.0:
     which "^1.3.0"
     yargs "^4.2.0"
 
+follow-redirects@^1.3.0:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.4.1.tgz#d8120f4518190f55aac65bb6fc7b85fcd666d6aa"
+  dependencies:
+    debug "^3.1.0"
+
 for-in@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"