Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
janhommes committed Oct 22, 2020
2 parents 3194bd7 + 3b0bebd commit f9d6e77
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 25 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ node_modules
npm-debug.log

dist
.rpt2_cache
.rpt2_cache

# WebStorm & IntelliJ Platfrom
.idea/
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 41 additions & 22 deletions src/OBatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export class OBatch {
this.batchConfig = { ...config, ...config.batch };
this.batchUid = this.getUid();
(this.batchConfig.headers as Headers).set(
"Content-Type",
`multipart/mixed;boundary=${this.batchUid}`,
"Content-Type",
`multipart/mixed; boundary=${this.batchUid}`,
);

if (this.batchConfig.batch.useChangset) {
Expand Down Expand Up @@ -48,6 +48,12 @@ export class OBatch {
}).join(`${CRLF}--${this.batchUid}`);

this.batchBody += `${CRLF}--${this.batchUid}--${CRLF}`;
if(!changeset){
(this.batchConfig.headers as Headers).set(
"Content-Type",
`multipart/mixed;boundary=${this.batchUid}`,
);
}
}

public async fetch(url: URL) {
Expand Down Expand Up @@ -77,11 +83,21 @@ export class OBatch {
const splitData = responseData.split(`--${boundary}`);
splitData.shift();
splitData.pop();
let wasWithChangesetresponse = false;
const parsedData = splitData.map((data) => {
const dataSegments = data.trim().split("\r\n\r\n");
if (dataSegments.length === 0 || dataSegments.length > 3) {
if (dataSegments.length === 0) {
// we are unable to parse -> return all
return data;
} else if (dataSegments.length > 3) {
const header = dataSegments.find(
(x) => x.startsWith("Content-Type: ") && x.includes("boundary=changesetresponse_"));
if (!header) {
return data;
}
dataSegments.shift();
wasWithChangesetresponse = true;
return this.parseResponse(dataSegments.join("\r\n\r\n"), header);
} else if (dataSegments.length === 3) {
// if length >= 3 we have a body, try to parse if JSON and return that!
try {
Expand All @@ -96,6 +112,9 @@ export class OBatch {
return +dataSegments[1].split(" ")[1];
}
});
if (wasWithChangesetresponse) {
return parsedData[0];
}
return parsedData;
}

Expand Down Expand Up @@ -158,27 +177,27 @@ export class OBatch {
}

private getHeaders(req: ORequest): string {
// Request headers can be Headers | string[][] | Record<string, string>.
// A new Headers instance around them allows treatment of all three types
// to be the same. This also applies security last two could bypass.
const headers = new Headers(req.config.headers || undefined) as any;
// Convert each header to single string.
// Headers is iterable. Array.from is needed instead of Object.keys.
const mapped = Array.from(headers).map(([k, v]) => `${k}: ${v}`);
if (mapped.length) {
// Need to ensure a blank line between HEADERS and BODY. When there are
// headers, it must be added here. Otherwise blank is added in ctor.
mapped.push("");
}
return mapped.join(CRLF);
// Request headers can be Headers | string[][] | Record<string, string>.
// A new Headers instance around them allows treatment of all three types
// to be the same. This also applies security last two could bypass.
const headers = new Headers(req.config.headers || undefined) as any;
// Convert each header to single string.
// Headers is iterable. Array.from is needed instead of Object.keys.
const mapped = Array.from(headers).map(([k, v]) => `${k}: ${v}`);
if (mapped.length) {
// Need to ensure a blank line between HEADERS and BODY. When there are
// headers, it must be added here. Otherwise blank is added in ctor.
mapped.push("");
}
return mapped.join(CRLF);
}

private getRequestURL(req: ORequest): string {
let href = req.url.href;
if (this.batchConfig.batch.useRelativeURLs) {
// Strip away matching root from request.
href = href.replace(this.batchConfig.rootUrl.href, '');
}
return href;
let href = req.url.href;
if (this.batchConfig.batch.useRelativeURLs) {
// Strip away matching root from request.
href = href.replace(this.batchConfig.rootUrl.href, '');
}
return href;
}
}
26 changes: 24 additions & 2 deletions src/o.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { o } from "./o";
import {o, OBatch} from "./o";

describe("initialize a new oHandler", () => {
test("url with string", () => {
Expand Down Expand Up @@ -358,7 +358,7 @@ describe("Create, Update and Delete request", () => {
beforeAll(async () => {
// Use the non restier service as it has CORS enabled
const response: Response = await o(
"https://services.odata.org/V4/TripPinServiceRW/",
"http://services.odata.org/V4/TripPinServiceRW/",
)
.get()
.fetch() as Response;
Expand Down Expand Up @@ -499,6 +499,28 @@ describe("Batching", () => {
expect(data[2].Name).toBe("New");
});

test("Batch POST and PATCH with useChangeset=true", async () => {
oHandler.config.batch.useChangset = true;

// given
const [resource1, resource2] = ["People", "Airlines('AA')"];
const resouce1data = {
FirstName: "Bar",
LastName: "Foo is cool",
UserName: "foobar" + Math.random(),
};
// when
const request = oHandler
.post(resource1, resouce1data)
.patch(resource2, { Name: "New" });
const batch = new OBatch(request.requests, request.config, null);
const data = await request.batch();
// expect
expect(data.length).toBe(2);
expect(data[0].LastName).toBe(resouce1data.LastName);
expect(data[1]).toBe(204);
});

// Content ID seems to have a problem in the test implementation (or I don't get the right implementation)
// tested with postman and I always get Resource not found for the segment '$1'
xtest("add something and directly patch it with Content-Id", async () => {
Expand Down

0 comments on commit f9d6e77

Please sign in to comment.