Skip to content

Commit

Permalink
refactor(:black_circle:): remove circular dependency in request
Browse files Browse the repository at this point in the history
AFFECTS PACKAGES:
@esri/arcgis-rest-request
  • Loading branch information
jgravois committed Nov 13, 2018
1 parent 7c89396 commit 9b58c63
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 186 deletions.
5 changes: 3 additions & 2 deletions packages/arcgis-rest-request/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
export * from "./request";
export * from "./utils/encode-form-data";
export * from "./utils/encode-query-string";
export * from "./utils/check-for-errors";
export * from "./utils/warn";
export * from "./utils/ArcGISRequestError";
export * from "./utils/ArcGISAuthError";
export * from "./utils/retryAuthError";
export * from "./utils/ErrorTypes";
export * from "./utils/params";
export * from "./utils/process-params";
export * from "./utils/get-portal";
export * from "./utils/get-portal-url";
Expand Down
161 changes: 110 additions & 51 deletions packages/arcgis-rest-request/src/request.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,12 @@
/* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */

import { checkForErrors } from "./utils/check-for-errors";
import { encodeFormData } from "./utils/encode-form-data";
import { encodeQueryString } from "./utils/encode-query-string";
import { requiresFormData } from "./utils/process-params";
import { ArcGISRequestError } from "./utils/ArcGISRequestError";

export type GrantTypes =
| "authorization_code"
| "refresh_token"
| "client_credentials"
| "exchange_refresh_token";

export interface IParams {
f?: ResponseFormats;
[key: string]: any;
}

export interface IGenerateTokenParams extends IParams {
username?: string;
password?: string;
expiration?: number;
token?: string;
serverUrl?: string;
}

export interface IFetchTokenParams extends IParams {
client_id: string;
client_secret?: string;
grant_type: GrantTypes;
redirect_uri?: string;
refresh_token?: string;
code?: string;
}

export interface ITokenRequestOptions {
params?: IGenerateTokenParams | IFetchTokenParams;
httpMethod?: HTTPMethods;
fetch?: (input: RequestInfo, init?: RequestInit) => Promise<Response>;
}
import { IRetryAuthError } from "./utils/retryAuthError";
import { HTTPMethods, IParams, ITokenRequestOptions } from "./utils/params";

/**
* Authentication can be supplied to `request` via [`UserSession`](../../auth/UserSession/) or [`ApplicationSession`](../../auth/ApplicationSession/). Both classes extend `IAuthenticationManager`.
Expand All @@ -62,22 +29,6 @@ export interface IAuthenticationManager {
getToken(url: string, requestOptions?: ITokenRequestOptions): Promise<string>;
}

/**
* HTTP methods used by the ArcGIS REST API.
*/
export type HTTPMethods = "GET" | "POST";

/**
* Valid response formats for the `f` parameter.
*/
export type ResponseFormats =
| "json"
| "geojson"
| "text"
| "html"
| "image"
| "zip";

/**
* Options for the `request()` method.
*/
Expand Down Expand Up @@ -291,3 +242,111 @@ export function request(
}
});
}

export class ArcGISAuthError extends ArcGISRequestError {
/**
* Create a new `ArcGISAuthError` object.
*
* @param message - The error message from the API
* @param code - The error code from the API
* @param response - The original response from the API that caused the error
* @param url - The original url of the request
* @param options - The original options of the request
*/
constructor(
message = "AUTHENTICATION_ERROR",
code: string | number = "AUTHENTICATION_ERROR_CODE",
response?: any,
url?: string,
options?: IRequestOptions
) {
super(message, code, response, url, options);
this.name = "ArcGISAuthError";
this.message =
code === "AUTHENTICATION_ERROR_CODE" ? message : `${code}: ${message}`;
}

retry(getSession: IRetryAuthError, retryLimit = 3) {
let tries = 0;

const retryRequest = (resolve: any, reject: any) => {
getSession(this.url, this.options)
.then(session => {
const newOptions = {
...this.options,
...{ authentication: session }
};

tries = tries + 1;
return request(this.url, newOptions);
})
.then(response => {
resolve(response);
})
.catch(e => {
if (e.name === "ArcGISAuthError" && tries < retryLimit) {
retryRequest(resolve, reject);
} else if (e.name === "ArcGISAuthError" && tries >= retryLimit) {
reject(this);
} else {
reject(e);
}
});
};

return new Promise((resolve, reject) => {
retryRequest(resolve, reject);
});
}
}

/**
* Checks for errors in a JSON response from the ArcGIS REST API. If there are no errors, it will return the `data` passed in. If there is an error, it will throw an `ArcGISRequestError` or `ArcGISAuthError`.
*
* @param data The response JSON to check for errors.
* @param url The url of the original request
* @param params The parameters of the original request
* @param options The options of the original request
* @returns The data that was passed in the `data` parameter
*/
export function checkForErrors(
response: any,
url?: string,
params?: IParams,
options?: IRequestOptions
): any {
// this is an error message from billing.arcgis.com backend
if (response.code >= 400) {
const { message, code } = response;
throw new ArcGISRequestError(message, code, response, url, options);
}

// error from ArcGIS Online or an ArcGIS Portal or server instance.
if (response.error) {
const { message, code, messageCode } = response.error;
const errorCode = messageCode || code || "UNKNOWN_ERROR_CODE";

if (code === 498 || code === 499 || messageCode === "GWM_0003") {
throw new ArcGISAuthError(message, errorCode, response, url, options);
}

throw new ArcGISRequestError(message, errorCode, response, url, options);
}

// error from a status check
if (response.status === "failed" || response.status === "failure") {
let message: string;
let code: string = "UNKNOWN_ERROR_CODE";

try {
message = JSON.parse(response.statusMessage).message;
code = JSON.parse(response.statusMessage).code;
} catch (e) {
message = response.statusMessage || response.message;
}

throw new ArcGISRequestError(message, code, response, url, options);
}

return response;
}
67 changes: 0 additions & 67 deletions packages/arcgis-rest-request/src/utils/ArcGISAuthError.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function appendCustomParams(
key !== "portal" &&
key !== "maxUrlLength" &&
key !== "endpoint" &&
key !== "fields"
key !== "formatCodedValues"
) {
newOptions.params[key] = (oldOptions as { [key: string]: any })[key];
}
Expand Down
65 changes: 0 additions & 65 deletions packages/arcgis-rest-request/src/utils/check-for-errors.ts

This file was deleted.

52 changes: 52 additions & 0 deletions packages/arcgis-rest-request/src/utils/params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* Copyright (c) 2017 Environmental Systems Research Institute, Inc.
* Apache-2.0 */

/**
* HTTP methods used by the ArcGIS REST API.
*/
export type HTTPMethods = "GET" | "POST";

/**
* Valid response formats for the `f` parameter.
*/
export type ResponseFormats =
| "json"
| "geojson"
| "text"
| "html"
| "image"
| "zip";

export type GrantTypes =
| "authorization_code"
| "refresh_token"
| "client_credentials"
| "exchange_refresh_token";

export interface IParams {
f?: ResponseFormats;
[key: string]: any;
}

export interface IGenerateTokenParams extends IParams {
username?: string;
password?: string;
expiration?: number;
token?: string;
serverUrl?: string;
}

export interface IFetchTokenParams extends IParams {
client_id: string;
client_secret?: string;
grant_type: GrantTypes;
redirect_uri?: string;
refresh_token?: string;
code?: string;
}

export interface ITokenRequestOptions {
params?: IGenerateTokenParams | IFetchTokenParams;
httpMethod?: HTTPMethods;
fetch?: (input: RequestInfo, init?: RequestInit) => Promise<Response>;
}
Loading

0 comments on commit 9b58c63

Please sign in to comment.