Skip to content

Commit cc1f3cf

Browse files
Merge pull request #89 from microsoftgraph/Fix-Stream-Request
Fix stream request
2 parents 2b968b5 + b4943f2 commit cc1f3cf

File tree

9 files changed

+152
-80
lines changed

9 files changed

+152
-80
lines changed

lib/graph-js-sdk-web.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/GraphRequest.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ export declare class GraphRequest {
3636
del(callback?: GraphRequestCallback): Promise<any>;
3737
get(callback?: GraphRequestCallback): Promise<any>;
3838
private routeResponseToPromise;
39+
private handleFetch;
3940
private routeResponseToCallback;
4041
private sendRequestAndRouteResponse;
4142
getStream(callback: GraphRequestCallback): void;
42-
putStream(stream: any, callback: Function): void;
43+
putStream(stream: any, callback: GraphRequestCallback): void;
44+
private getDefaultRequestHeaders;
4345
private configureRequest;
4446
query(queryDictionaryOrString: string | {
4547
[key: string]: string | number;

lib/src/GraphRequest.js

Lines changed: 51 additions & 33 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/GraphRequest.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/common.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export interface URLComponents {
2222
[key: string]: string | number;
2323
};
2424
}
25+
export interface DefaultRequestHeaders {
26+
Authorization: string;
27+
SdkVersion: string;
28+
}
2529
export interface GraphRequestCallback {
2630
(error: GraphError, response: any, rawResponse?: any): void;
2731
}

samples/node/node-sample.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const MicrosoftGraph = require("../../lib/src/index.js").Client;
77

88
const secrets = require("./secrets");
99

10+
const fs = require("fs");
11+
1012
const client = MicrosoftGraph.init({
1113
defaultVersion: 'v1.0',
1214
debugLogging: true,

spec/types/miscellaneous.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import { assert } from 'chai'
1717
import { getClient, randomString } from "./test-helper"
18+
import * as fs from "fs";
1819

1920

2021
declare const describe, it;
@@ -188,6 +189,31 @@ describe('Test for GET and PUT binary data', function () {
188189
});
189190
});
190191

192+
describe("Test for PUT and GET streams", function () {
193+
this.timeout(10 * 1000);
194+
beforeEach((done) => {
195+
setTimeout(function () {
196+
done();
197+
}, 1000);
198+
});
199+
const imageFileName = `stream-image-${randomString()}.png`;
200+
it("Uploading drive item as a stream", (done) => {
201+
let stream = fs.createReadStream('./sample.png');
202+
return getClient().api(`/me/drive/root/children/${imageFileName}/content`).putStream(stream, (err) => {
203+
assert.isTrue(err === null);
204+
done();
205+
});
206+
});
207+
208+
it("GET drive item as a stream", (done) => {
209+
return getClient().api(`/me/drive/root:${imageFileName}:/content`).getStream((err, stream) => {
210+
let writeStream = fs.createWriteStream(`./${imageFileName}`);
211+
stream.pipe(writeStream).on('error', assert.fail);
212+
done();
213+
})
214+
});
215+
});
216+
191217

192218

193219

src/GraphRequest.ts

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Promise } from 'es6-promise'
22
import 'isomorphic-fetch';
33

4-
import { Options, URLComponents, GraphError, oDataQueryNames, GraphRequestCallback, PACKAGE_VERSION } from "./common"
4+
import { Options, URLComponents, GraphError, oDataQueryNames, GraphRequestCallback, PACKAGE_VERSION, DefaultRequestHeaders } from "./common"
55
import { ResponseHandler } from "./ResponseHandler"
66
import { RequestMethod } from './RequestMethod';
77
import { GraphHelper } from './GraphHelper';
@@ -269,8 +269,6 @@ export class GraphRequest {
269269
);
270270
}
271271

272-
273-
// Given the built SuperAgentRequest, get an auth token from the authProvider, make the request and return a promise
274272
private routeResponseToPromise(request: Request) {
275273
return new Promise((resolve, reject) => {
276274
this.routeResponseToCallback(request, (err, body) => {
@@ -283,19 +281,26 @@ export class GraphRequest {
283281
});
284282
}
285283

286-
// Given the built SuperAgentRequest, get an auth token from the authProvider, make the request and invoke the callback
284+
// Given the Request object, make the request and invoke callback
285+
private handleFetch(request: Request | string, callback: GraphRequestCallback, options?: any) {
286+
((request.constructor.name === "Request") ? fetch(request) : fetch(request, options)).then((response) => {
287+
this.convertResponseType(response).then((responseValue) => {
288+
ResponseHandler.init(response, undefined, responseValue, callback);
289+
}).catch((error) => {
290+
ResponseHandler.init(response, error, undefined, callback)
291+
});
292+
}).catch((error) => {
293+
ResponseHandler.init(undefined, error, undefined, callback)
294+
});
295+
}
296+
297+
// Given the Request object, get an auth token from the authProvider, make the fetch call
287298
private routeResponseToCallback(request: Request, callback: GraphRequestCallback) {
288-
this.config.authProvider((err, accessToken) => {
299+
let self = this;
300+
self.config.authProvider((err, accessToken) => {
289301
if (err == null && accessToken != null) {
290-
fetch(this.configureRequest(request, accessToken)).then((response) => {
291-
this.convertResponseType(response).then((responseValue) => {
292-
ResponseHandler.init(response, undefined, responseValue, callback);
293-
}).catch((error) => {
294-
ResponseHandler.init(response, error, undefined, callback)
295-
});
296-
}).catch((error) => {
297-
ResponseHandler.init(undefined, error, undefined, callback)
298-
});
302+
request = self.configureRequest(request, accessToken);
303+
self.handleFetch(request, callback);
299304
} else {
300305
callback(err, null, null);
301306
}
@@ -316,48 +321,55 @@ export class GraphRequest {
316321
}
317322

318323
getStream(callback: GraphRequestCallback) {
319-
this.config.authProvider((err, accessToken) => {
324+
let self = this;
325+
self.config.authProvider((err, accessToken) => {
320326
if (err === null && accessToken !== null) {
321-
let url = this.buildFullUrl();
322-
callback(null, this.configureRequest(
323-
new Request(url, { method: RequestMethod.GET, headers: new Headers() }),
324-
accessToken));
327+
let url = self.buildFullUrl();
328+
let options = {
329+
method: RequestMethod.GET,
330+
headers: self.getDefaultRequestHeaders(accessToken)
331+
};
332+
self.responseType("stream");
333+
Object.keys(self._headers).forEach((key) => options.headers[key] = self._headers[key] as string);
334+
self.handleFetch(url, callback, options);
325335
} else {
326336
callback(err, null);
327337
}
328338
});
329339
}
330340

331-
putStream(stream: any, callback: Function) {
332-
this.config.authProvider((err, accessToken) => {
341+
putStream(stream: any, callback: GraphRequestCallback) {
342+
let self = this;
343+
self.config.authProvider((err, accessToken) => {
333344
if (err === null && accessToken !== null) {
334-
let url = this.buildFullUrl();
335-
let req: Request = this.configureRequest(
336-
new Request(
337-
url,
338-
{
339-
method: RequestMethod.PUT,
340-
headers: new Headers({ 'Content-Type': 'application/octet-stream' })
341-
}),
342-
accessToken
343-
);
344-
stream
345-
.pipe(req)
346-
.on('error', function (err) {
347-
callback(err, null)
348-
})
349-
.on('end', function () {
350-
callback(null)
351-
});
345+
let url = self.buildFullUrl();
346+
let options = {
347+
method: RequestMethod.PUT,
348+
headers: {
349+
'Content-Type': 'application/octet-stream',
350+
},
351+
body: stream
352+
}
353+
let defaultHeaders = self.getDefaultRequestHeaders(accessToken);
354+
Object.keys(defaultHeaders).forEach((key) => options.headers[key] = defaultHeaders[key] as string);
355+
Object.keys(self._headers).forEach((key) => options.headers[key] = self._headers[key] as string);
356+
self.handleFetch(url, callback, options);
352357
}
353358
});
354359
}
355360

356-
private configureRequest(request: Request, accessToken: string): Request {
357-
request.headers.append('Authorization', 'Bearer ' + accessToken);
358-
request.headers.append('SdkVersion', "graph-js-" + PACKAGE_VERSION);
361+
private getDefaultRequestHeaders(accessToken: string): DefaultRequestHeaders {
362+
return {
363+
Authorization: `Bearer ${accessToken}`,
364+
SdkVersion: `graph-js-${PACKAGE_VERSION}`
365+
}
366+
}
359367

360-
Object.keys(this._headers).forEach((key) => request.headers.set(key, this._headers[key] as string));
368+
private configureRequest(request: Request, accessToken: string): Request {
369+
let self = this,
370+
defaultHeaders = self.getDefaultRequestHeaders(accessToken);
371+
Object.keys(defaultHeaders).forEach((key) => request.headers.set(key, defaultHeaders[key] as string));
372+
Object.keys(self._headers).forEach((key) => request.headers.set(key, self._headers[key] as string));
361373
return request;
362374
}
363375

@@ -424,6 +436,9 @@ export class GraphRequest {
424436
case "text":
425437
responseValue = response.text();
426438
break;
439+
case "stream":
440+
responseValue = Promise.resolve(response.body);
441+
break;
427442
default:
428443
responseValue = response.json();
429444
break;

src/common.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export interface URLComponents {
2929
otherURLQueryParams:{ [key: string] : string|number; }
3030
}
3131

32+
export interface DefaultRequestHeaders {
33+
Authorization: string
34+
SdkVersion: string
35+
}
36+
3237
export interface GraphRequestCallback {
3338
(error: GraphError, response: any, rawResponse?: any): void
3439
}
@@ -45,4 +50,4 @@ export interface GraphError {
4550
requestId: string, // "ca269f81-55d7-483f-a9e6-2b04a2a2d0e2"
4651
date: Date, // new Date(2016-11-17T18:49:59)
4752
body: string // original graph response
48-
}
53+
}

0 commit comments

Comments
 (0)