Skip to content

Commit f9bd623

Browse files
Fix double uri encoding when expand query used
1 parent d26ee49 commit f9bd623

11 files changed

+142
-11
lines changed

DynamicsWebApi.njsproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<OutputPath>.</OutputPath>
2727
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
2828
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
29-
<ProjectView>ProjectFiles</ProjectView>
29+
<ProjectView>ShowAllFiles</ProjectView>
3030
<NodejsPort>1337</NodejsPort>
3131
<StartWebBrowser>True</StartWebBrowser>
3232
</PropertyGroup>

dist/dynamics-web-api-callbacks.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ function stringifyData(data, config) {
357357
}
358358
//add full web api url if it's not set
359359
if (!value.startsWith(config.webApiUrl)) {
360-
value = config.webApiUrl + value;
360+
value = config.webApiUrl + value.replace(/^\\/, '');
361361
}
362362
}
363363
}
@@ -593,7 +593,7 @@ function convertRequestOptions(request, functionName, url, joinSymbol, config) {
593593
}
594594
}
595595
if (expandRequestArray.length) {
596-
requestArray.push("$expand=" + encodeURI(expandRequestArray.join(",")));
596+
requestArray.push("$expand=" + (expandRequestArray.join(",")));
597597
}
598598
}
599599
}

dist/dynamics-web-api-callbacks.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/dynamics-web-api.js

+25-2
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ function stringifyData(data, config) {
357357
}
358358
//add full web api url if it's not set
359359
if (!value.startsWith(config.webApiUrl)) {
360-
value = config.webApiUrl + value;
360+
value = config.webApiUrl + value.replace(/^\\/, '');
361361
}
362362
}
363363
}
@@ -593,7 +593,7 @@ function convertRequestOptions(request, functionName, url, joinSymbol, config) {
593593
}
594594
}
595595
if (expandRequestArray.length) {
596-
requestArray.push("$expand=" + encodeURI(expandRequestArray.join(",")));
596+
requestArray.push("$expand=" + (expandRequestArray.join(",")));
597597
}
598598
}
599599
}
@@ -723,6 +723,29 @@ if (!String.prototype.endsWith || !String.prototype.startsWith) {
723723
* @property {string} returnRepresentation - Sets Prefer header request with value "return=representation". Use this property to return just created or updated entity in a single request.
724724
*/
725725

726+
/**
727+
* Dynamics Web Api Request
728+
* @typedef {Object} DWARequest
729+
* @property {string} collection
730+
* @property {string} id
731+
* @property {Array} select
732+
* @property {Array} expand
733+
* @property {string} filter
734+
* @property {number} maxPageSize
735+
* @property {boolean} count
736+
* @property {number} top
737+
* @property {Array} orderBy
738+
* @property {string} includeAnnotations
739+
* @property {string} ifmatch
740+
* @property {string} ifnonematch
741+
* @property {boolean} returnRepresentation
742+
* @property {Object} entity
743+
* @property {string} impersonate: "",
744+
* @property {string} navigationProperty: "",
745+
* @property {string} savedQuery: "",
746+
* @property {string} userQuery: ""
747+
*/
748+
726749
/**
727750
* DynamicsWebApi - a Microsoft Dynamics CRM Web API helper library. Current version uses Promises instead of Callbacks.
728751
*

dist/dynamics-web-api.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/dynamics-web-api.js

+23
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,29 @@ var dwaRequest = function () {
5555
* @property {string} returnRepresentation - Sets Prefer header request with value "return=representation". Use this property to return just created or updated entity in a single request.
5656
*/
5757

58+
/**
59+
* Dynamics Web Api Request
60+
* @typedef {Object} DWARequest
61+
* @property {string} collection
62+
* @property {string} id
63+
* @property {Array} select
64+
* @property {Array} expand
65+
* @property {string} filter
66+
* @property {number} maxPageSize
67+
* @property {boolean} count
68+
* @property {number} top
69+
* @property {Array} orderBy
70+
* @property {string} includeAnnotations
71+
* @property {string} ifmatch
72+
* @property {string} ifnonematch
73+
* @property {boolean} returnRepresentation
74+
* @property {Object} entity
75+
* @property {string} impersonate: "",
76+
* @property {string} navigationProperty: "",
77+
* @property {string} savedQuery: "",
78+
* @property {string} userQuery: ""
79+
*/
80+
5881
/**
5982
* DynamicsWebApi - a Microsoft Dynamics CRM Web API helper library. Current version uses Promises instead of Callbacks.
6083
*

lib/requests/sendRequest.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function stringifyData(data, config) {
3636
}
3737
//add full web api url if it's not set
3838
if (!value.startsWith(config.webApiUrl)) {
39-
value = config.webApiUrl + value;
39+
value = config.webApiUrl + value.replace(/^\\/, '');
4040
}
4141
}
4242
}

lib/utilities/RequestConverter.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ function convertRequestOptions(request, functionName, url, joinSymbol, config) {
120120
if (request.expand && request.expand.length) {
121121
ErrorHelper.stringOrArrayParameterCheck(request.expand, "DynamicsWebApi." + functionName, "request.expand");
122122
if (typeof request.expand === "string") {
123-
requestArray.push("$expand=" + encodeURI(request.expand));
123+
requestArray.push("$expand=" + request.expand);
124124
}
125125
else {
126126
var expandRequestArray = [];
@@ -135,7 +135,7 @@ function convertRequestOptions(request, functionName, url, joinSymbol, config) {
135135
}
136136
}
137137
if (expandRequestArray.length) {
138-
requestArray.push("$expand=" + encodeURI(expandRequestArray.join(",")));
138+
requestArray.push("$expand=" + expandRequestArray.join(","));
139139
}
140140
}
141141
}

tests/callbacks-tests.js

+41
Original file line numberDiff line numberDiff line change
@@ -2185,6 +2185,47 @@ describe("callbacks -", function () {
21852185
});
21862186
});
21872187

2188+
describe("basic - expand filter", function () {
2189+
var scope;
2190+
before(function () {
2191+
var response = mocks.responses.response200;
2192+
scope = nock(mocks.responses.testEntityUrl, {
2193+
reqheaders: {
2194+
'If-Match': 'match',
2195+
'MSCRMCallerID': mocks.data.testEntityId2
2196+
}
2197+
})
2198+
.get("?$expand=prop($filter=" + encodeURI("field eq ") + '%27value%27)')
2199+
.reply(response.status, response.responseText, response.responseHeaders);
2200+
});
2201+
2202+
after(function () {
2203+
nock.cleanAll();
2204+
});
2205+
2206+
it("returns a correct response", function (done) {
2207+
var dwaRequest = {
2208+
id: mocks.data.testEntityId,
2209+
collection: "tests",
2210+
expand: [{ property: "prop", filter: "field eq 'value'" }],
2211+
impersonate: mocks.data.testEntityId2,
2212+
ifmatch: "match"
2213+
};
2214+
2215+
dynamicsWebApiTest.retrieveRequest(dwaRequest, function (object) {
2216+
expect(object).to.deep.equal(mocks.data.testEntity);
2217+
done();
2218+
}, function (object) {
2219+
expect(object).to.be.undefined;
2220+
done();
2221+
});
2222+
});
2223+
2224+
it("all requests have been made", function () {
2225+
expect(scope.isDone()).to.be.true;
2226+
});
2227+
});
2228+
21882229
describe("retrieve reference", function () {
21892230
var scope;
21902231
before(function () {

tests/common-tests.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ describe("RequestConverter.convertRequestOptions -", function () {
191191
};
192192

193193
var result = RequestConverter.convertRequestOptions(dwaRequest, "", stubUrl);
194-
expect(result).to.deep.equal({ url: stubUrl, query: "$expand=property($filter=" + encodeURI("name eq 'name'") + ")", headers: {} });
194+
expect(result).to.deep.equal({ url: stubUrl, query: "$expand=property($filter=" + ("name eq 'name'") + ")", headers: {} });
195195
});
196196

197197
it("expand - property,orderBy empty", function () {

tests/main-tests.js

+44
Original file line numberDiff line numberDiff line change
@@ -2263,6 +2263,50 @@ describe("promises -", function () {
22632263
});
22642264
});
22652265

2266+
describe("basic - expand filter", function () {
2267+
var scope;
2268+
before(function () {
2269+
var response = mocks.responses.response200;
2270+
scope = nock(mocks.responses.testEntityUrl, {
2271+
reqheaders: {
2272+
'If-Match': 'match',
2273+
'MSCRMCallerID': mocks.data.testEntityId2
2274+
}
2275+
})
2276+
.get("?$expand=prop($filter=" + encodeURI("field eq ") + '%27value%27)')
2277+
.reply(response.status, response.responseText, response.responseHeaders);
2278+
});
2279+
2280+
after(function () {
2281+
nock.cleanAll();
2282+
});
2283+
2284+
it("returns a correct response", function (done) {
2285+
var dwaRequest = {
2286+
id: mocks.data.testEntityId,
2287+
collection: "tests",
2288+
expand: [{ property: "prop", filter: "field eq 'value'" }],
2289+
impersonate: mocks.data.testEntityId2,
2290+
ifmatch: "match"
2291+
};
2292+
2293+
console.error(encodeURI(dwaRequest.expand[0].filter));
2294+
2295+
dynamicsWebApiTest.retrieveRequest(dwaRequest)
2296+
.then(function (object) {
2297+
expect(object).to.deep.equal(mocks.data.testEntity);
2298+
done();
2299+
}).catch(function (object) {
2300+
expect(object).to.be.undefined;
2301+
done();
2302+
});
2303+
});
2304+
2305+
it("all requests have been made", function () {
2306+
expect(scope.isDone()).to.be.true;
2307+
});
2308+
});
2309+
22662310
describe("retrieve reference", function () {
22672311
var scope;
22682312
before(function () {

0 commit comments

Comments
 (0)