diff --git a/packages/arcgis-rest-geocoder/src/bulk.ts b/packages/arcgis-rest-geocoder/src/bulk.ts index 72e767cbaa..c6919c50c8 100644 --- a/packages/arcgis-rest-geocoder/src/bulk.ts +++ b/packages/arcgis-rest-geocoder/src/bulk.ts @@ -1,7 +1,7 @@ /* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc. * Apache-2.0 */ -import { request } from "@esri/arcgis-rest-request"; +import { request, cleanUrl } from "@esri/arcgis-rest-request"; import { ISpatialReference, IPoint } from "@esri/arcgis-rest-common-types"; @@ -86,15 +86,16 @@ export function bulkGeocode( ); } - return request(options.endpoint + "geocodeAddresses", options).then( - response => { - const sr = response.spatialReference; - response.locations.forEach(function(address: { location: IPoint }) { - address.location.spatialReference = sr; - }); - return response; - } - ); + return request( + `${cleanUrl(options.endpoint)}/geocodeAddresses`, + options + ).then(response => { + const sr = response.spatialReference; + response.locations.forEach(function(address: { location: IPoint }) { + address.location.spatialReference = sr; + }); + return response; + }); } export default { diff --git a/packages/arcgis-rest-geocoder/src/geocode.ts b/packages/arcgis-rest-geocoder/src/geocode.ts index 6cd75e8e0e..10538ba6e6 100644 --- a/packages/arcgis-rest-geocoder/src/geocode.ts +++ b/packages/arcgis-rest-geocoder/src/geocode.ts @@ -4,7 +4,8 @@ import { request, IParams, - appendCustomParams + appendCustomParams, + cleanUrl } from "@esri/arcgis-rest-request"; import { @@ -108,21 +109,22 @@ export function geocode( } // add spatialReference property to individual matches - return request(options.endpoint + "findAddressCandidates", options).then( - response => { - const sr = response.spatialReference; - response.candidates.forEach(function(candidate: { - location: IPoint; - extent?: IExtent; - }) { - candidate.location.spatialReference = sr; - if (candidate.extent) { - candidate.extent.spatialReference = sr; - } - }); - return response; - } - ); + return request( + `${cleanUrl(options.endpoint)}/findAddressCandidates`, + options + ).then(response => { + const sr = response.spatialReference; + response.candidates.forEach(function(candidate: { + location: IPoint; + extent?: IExtent; + }) { + candidate.location.spatialReference = sr; + if (candidate.extent) { + candidate.extent.spatialReference = sr; + } + }); + return response; + }); } export default { diff --git a/packages/arcgis-rest-geocoder/src/reverse.ts b/packages/arcgis-rest-geocoder/src/reverse.ts index 0fef4b02cf..fea5554ed0 100644 --- a/packages/arcgis-rest-geocoder/src/reverse.ts +++ b/packages/arcgis-rest-geocoder/src/reverse.ts @@ -1,7 +1,7 @@ /* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc. * Apache-2.0 */ -import { request } from "@esri/arcgis-rest-request"; +import { request, cleanUrl } from "@esri/arcgis-rest-request"; import { IPoint } from "@esri/arcgis-rest-common-types"; import { ILocation, worldGeocoder, IEndpointRequestOptions } from "./helpers"; @@ -75,7 +75,7 @@ export function reverseGeocode( options.params.location = coords; } - return request(options.endpoint + "reverseGeocode", options); + return request(`${cleanUrl(options.endpoint)}/reverseGeocode`, options); } export default { diff --git a/packages/arcgis-rest-geocoder/src/suggest.ts b/packages/arcgis-rest-geocoder/src/suggest.ts index fc6feb5433..fbb63d84a9 100644 --- a/packages/arcgis-rest-geocoder/src/suggest.ts +++ b/packages/arcgis-rest-geocoder/src/suggest.ts @@ -1,7 +1,7 @@ /* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc. * Apache-2.0 */ -import { request } from "@esri/arcgis-rest-request"; +import { request, cleanUrl } from "@esri/arcgis-rest-request"; import { worldGeocoder, IEndpointRequestOptions } from "./helpers"; @@ -61,7 +61,7 @@ export function suggest( options.params.magicKey = requestOptions.magicKey; } - return request(options.endpoint + "suggest", options); + return request(`${cleanUrl(options.endpoint)}/suggest`, options); } export default { diff --git a/packages/arcgis-rest-request/src/index.ts b/packages/arcgis-rest-request/src/index.ts index c499a2ad3d..336d613097 100644 --- a/packages/arcgis-rest-request/src/index.ts +++ b/packages/arcgis-rest-request/src/index.ts @@ -13,3 +13,4 @@ export * from "./utils/process-params"; export * from "./utils/get-portal"; export * from "./utils/get-portal-url"; export * from "./utils/append-custom-params"; +export * from "./utils/clean-url"; diff --git a/packages/arcgis-rest-request/src/utils/clean-url.ts b/packages/arcgis-rest-request/src/utils/clean-url.ts new file mode 100644 index 0000000000..0bc6fd52de --- /dev/null +++ b/packages/arcgis-rest-request/src/utils/clean-url.ts @@ -0,0 +1,16 @@ +/* Copyright (c) 2018 Environmental Systems Research Institute, Inc. + * Apache-2.0 */ + +/** + * Helper method to ensure that user supplied urls don't include whitespace or a trailing slash. + */ +export function cleanUrl(url: string) { + // trim leading and trailing spaces, but not spaces inside the url + url = url.trim(); + + // remove the trailing slash to the url if one was included + if (url[url.length - 1] === "/") { + url = url.slice(0, -1); + } + return url; +} diff --git a/packages/arcgis-rest-request/src/utils/get-portal-url.ts b/packages/arcgis-rest-request/src/utils/get-portal-url.ts index 755861337c..e4b15ec652 100644 --- a/packages/arcgis-rest-request/src/utils/get-portal-url.ts +++ b/packages/arcgis-rest-request/src/utils/get-portal-url.ts @@ -1,7 +1,7 @@ /* Copyright (c) 2017 Environmental Systems Research Institute, Inc. * Apache-2.0 */ import { IRequestOptions } from "../request"; - +import { cleanUrl } from "./clean-url"; /** * Helper that returns the appropriate portal url for a given request. `requestOptions.portal` is given * precedence over `authentication.portal`. If neither are present, `www.arcgis.com/sharing/rest` is returned. @@ -12,12 +12,12 @@ import { IRequestOptions } from "../request"; export function getPortalUrl(requestOptions: IRequestOptions = {}): string { // use portal in options if specified if (requestOptions.portal) { - return requestOptions.portal; + return cleanUrl(requestOptions.portal); } // if auth was passed, use that portal if (requestOptions.authentication) { - return requestOptions.authentication.portal; + return cleanUrl(requestOptions.authentication.portal); } // default to arcgis.com diff --git a/packages/arcgis-rest-request/test/utils/clean-url.test.ts b/packages/arcgis-rest-request/test/utils/clean-url.test.ts new file mode 100644 index 0000000000..134e172322 --- /dev/null +++ b/packages/arcgis-rest-request/test/utils/clean-url.test.ts @@ -0,0 +1,47 @@ +/* Copyright (c) 2018 Environmental Systems Research Institute, Inc. + * Apache-2.0 */ + +import { cleanUrl } from "../../src/utils/clean-url"; + +const validUrl = + "https://server.com/arcgis/rest/services/Custom Space/MapServer"; + +describe("cleanUrl", () => { + it("should not mangle a valid url", () => { + expect( + cleanUrl( + "https://server.com/arcgis/rest/services/Custom Space/MapServer/" + ) + ).toEqual(validUrl); + }); + + it("should add a trailing slash", () => { + expect( + cleanUrl("https://server.com/arcgis/rest/services/Custom Space/MapServer") + ).toEqual(validUrl); + }); + + it("should remove leading whitespace", () => { + expect( + cleanUrl( + " https://server.com/arcgis/rest/services/Custom Space/MapServer/" + ) + ).toEqual(validUrl); + }); + + it("should remove trailing whitespace", () => { + expect( + cleanUrl( + "https://server.com/arcgis/rest/services/Custom Space/MapServer/ " + ) + ).toEqual(validUrl); + }); + + it("should do it all at once", () => { + expect( + cleanUrl( + " https://server.com/arcgis/rest/services/Custom Space/MapServer " + ) + ).toEqual(validUrl); + }); +});