Skip to content

Commit

Permalink
fix: force FormData when calling /updateResources
Browse files Browse the repository at this point in the history
AFFECTS PACKAGES:
@esri/arcgis-rest-request
@esri/arcgis-rest-items

ISSUES CLOSED: #499
  • Loading branch information
jgravois committed Apr 2, 2019
1 parent 9d79fe0 commit 24af241
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 54 deletions.
15 changes: 9 additions & 6 deletions packages/arcgis-rest-items/src/update.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */

import { request, getPortalUrl } from "@esri/arcgis-rest-request";
import {
request,
getPortalUrl,
IRequestOptions
} from "@esri/arcgis-rest-request";

import { IItemUpdate } from "@esri/arcgis-rest-common-types";

Expand Down Expand Up @@ -87,9 +91,9 @@ export function updateItemResource(
requestOptions: IItemResourceRequestOptions
): Promise<any> {
const owner = determineOwner(requestOptions);
const url = `${getPortalUrl(requestOptions)}/content/users/${owner}/items/${
requestOptions.id
}/updateResources`;
const url = `${getPortalUrl(
requestOptions as IRequestOptions
)}/content/users/${owner}/items/${requestOptions.id}/updateResources`;

// mix in user supplied params
requestOptions.params = {
Expand All @@ -99,13 +103,12 @@ export function updateItemResource(
...requestOptions.params
};

// only override whatever access was specified previously if 'private' was passed explicitly
// only override the access specified previously if 'private' is passed explicitly
if (typeof requestOptions.private !== "undefined") {
requestOptions.params.access = requestOptions.private
? "private"
: "inherit";
}

return request(url, requestOptions);
}

Expand Down
90 changes: 48 additions & 42 deletions packages/arcgis-rest-items/test/update.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,19 +214,21 @@ describe("search", () => {
content: "jumbotron",
...MOCK_USER_REQOPTS
})
.then(response => {
.then(() => {
const [url, options]: [string, RequestInit] = fetchMock.lastCall("*");
expect(url).toEqual(
"https://myorg.maps.arcgis.com/sharing/rest/content/users/dbouwman/items/3ef/updateResources"
);
expect(options.method).toBe("POST");
expect(options.body).toContain("f=json");
expect(options.body).toContain(
encodeParam("fileName", "image/banner.png")
);
expect(options.body).toContain(encodeParam("text", "jumbotron"));
expect(options.body).not.toContain(encodeParam("access", "inherit"));
expect(options.body).toContain(encodeParam("token", "fake-token"));
expect(options.body instanceof FormData).toBeTruthy();
const params = options.body as FormData;
if (params.get) {
expect(params.get("f")).toEqual("json");
expect(params.get("fileName")).toEqual("image/banner.png");
expect(params.get("text")).toEqual("jumbotron");
expect(params.get("access")).toEqual(null);
expect(params.get("token")).toEqual("fake-token");
}
done();
})
.catch(e => {
Expand All @@ -235,10 +237,7 @@ describe("search", () => {
});

it("should update a binary resource to an item", done => {
fetchMock.once("*", {
success: true
});

fetchMock.once("*", { success: true });
const file = attachmentFile();

updateItemResource({
Expand Down Expand Up @@ -279,18 +278,21 @@ describe("search", () => {
content: "jumbotron",
...MOCK_USER_REQOPTS
})
.then(response => {
.then(() => {
const [url, options]: [string, RequestInit] = fetchMock.lastCall("*");
expect(url).toEqual(
"https://myorg.maps.arcgis.com/sharing/rest/content/users/casey/items/3ef/updateResources"
);
expect(options.method).toBe("POST");
expect(options.body).toContain("f=json");
expect(options.body).toContain(
encodeParam("fileName", "image/banner.png")
);
expect(options.body).toContain(encodeParam("text", "jumbotron"));
expect(options.body).toContain(encodeParam("token", "fake-token"));
expect(options.body instanceof FormData).toBeTruthy();
const params = options.body as FormData;
if (params.get) {
expect(params.get("f")).toEqual("json");
expect(params.get("fileName")).toEqual("image/banner.png");
expect(params.get("text")).toEqual("jumbotron");
expect(params.get("access")).toEqual(null);
expect(params.get("token")).toEqual("fake-token");
}
done();
})
.catch(e => {
Expand All @@ -315,14 +317,16 @@ describe("search", () => {
"https://myorg.maps.arcgis.com/sharing/rest/content/users/casey/items/3ef/updateResources"
);
expect(options.method).toBe("POST");
expect(options.body).toContain("f=json");
expect(options.body).toContain(
encodeParam("fileName", "image/banner.png")
);
expect(options.body).toContain("resourcesPrefix=foolder");
expect(options.body).toContain(encodeParam("text", "jumbotron"));
expect(options.body).toContain(encodeParam("token", "fake-token"));
expect(options.body).not.toContain(encodeParam("access", "inherit"));
expect(options.body instanceof FormData).toBeTruthy();
const params = options.body as FormData;
if (params.get) {
expect(params.get("f")).toEqual("json");
expect(params.get("fileName")).toEqual("image/banner.png");
expect(params.get("resourcesPrefix")).toEqual("foolder");
expect(params.get("text")).toEqual("jumbotron");
expect(params.get("access")).toEqual(null);
expect(params.get("token")).toEqual("fake-token");
}
done();
})
.catch(e => {
Expand All @@ -335,7 +339,6 @@ describe("search", () => {
updateItemResource({
id: "3ef",
name: "image/banner.png",
content: "jumbotron",
private: true,
...MOCK_USER_REQOPTS
})
Expand All @@ -345,13 +348,14 @@ describe("search", () => {
"https://myorg.maps.arcgis.com/sharing/rest/content/users/casey/items/3ef/updateResources"
);
expect(options.method).toBe("POST");
expect(options.body).toContain("f=json");
expect(options.body).toContain(
encodeParam("fileName", "image/banner.png")
);
expect(options.body).toContain(encodeParam("text", "jumbotron"));
expect(options.body).toContain(encodeParam("token", "fake-token"));
expect(options.body).toContain(encodeParam("access", "private"));
expect(options.body instanceof FormData).toBeTruthy();
const params = options.body as FormData;
if (params.get) {
expect(params.get("f")).toEqual("json");
expect(params.get("fileName")).toEqual("image/banner.png");
expect(params.get("access")).toEqual("private");
expect(params.get("token")).toEqual("fake-token");
}
done();
})
.catch(e => {
Expand All @@ -374,13 +378,15 @@ describe("search", () => {
"https://myorg.maps.arcgis.com/sharing/rest/content/users/casey/items/3ef/updateResources"
);
expect(options.method).toBe("POST");
expect(options.body).toContain("f=json");
expect(options.body).toContain(
encodeParam("fileName", "image/banner.png")
);
expect(options.body).toContain(encodeParam("text", "jumbotron"));
expect(options.body).toContain(encodeParam("token", "fake-token"));
expect(options.body).toContain(encodeParam("access", "inherit"));
expect(options.body instanceof FormData).toBeTruthy();
const params = options.body as FormData;
if (params.get) {
expect(params.get("f")).toEqual("json");
expect(params.get("fileName")).toEqual("image/banner.png");
expect(params.get("text")).toEqual("jumbotron");
expect(params.get("access")).toEqual("inherit");
expect(params.get("token")).toEqual("fake-token");
}
done();
})
.catch(e => {
Expand Down
9 changes: 7 additions & 2 deletions packages/arcgis-rest-request/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,13 @@ export function request(
}
}

/* updateResources currently requires FormData even when the input parameters dont warrant it.
https://developers.arcgis.com/rest/users-groups-and-items/update-resources.htm
see https://github.com/Esri/arcgis-rest-js/pull/500 for more info. */
const forceFormData = new RegExp("/items/.+/updateResources").test(url);

if (fetchOptions.method === "POST") {
fetchOptions.body = encodeFormData(params);
fetchOptions.body = encodeFormData(params, forceFormData);
}

// Mixin headers from request options
Expand All @@ -201,7 +206,7 @@ export function request(
}

/* istanbul ignore else blob responses are difficult to make cross platform we will just have to trust the isomorphic fetch will do its job */
if (!requiresFormData(params)) {
if (!requiresFormData(params) && !forceFormData) {
fetchOptions.headers["Content-Type"] =
"application/x-www-form-urlencoded";
}
Expand Down
8 changes: 6 additions & 2 deletions packages/arcgis-rest-request/src/utils/encode-form-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import { encodeQueryString } from "./encode-query-string";
* @param params An object to be encoded.
* @returns The complete [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object.
*/
export function encodeFormData(params: any): FormData | string {
const useFormData = requiresFormData(params);
export function encodeFormData(
params: any,
forceFormData?: boolean
): FormData | string {
// see https://github.com/Esri/arcgis-rest-js/issues/499 for more info.
const useFormData = requiresFormData(params) || forceFormData;
const newParams = processParams(params);
if (useFormData) {
const formData = new FormData();
Expand Down
2 changes: 1 addition & 1 deletion packages/arcgis-rest-request/src/utils/process-params.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (c) 2017 Environmental Systems Research Institute, Inc.
* Apache-2.0 */
* Apache-2.0 */

/**
* Checks parameters to see if we should use FormData to send the request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe("processParams", () => {
expect(processParams(params)).toEqual(expected);
});

it("should stringify arrays of objects", () => {
it("should stringify arrays of objects", () => {
const params = {
foo: [
{
Expand Down

0 comments on commit 24af241

Please sign in to comment.