-
Notifications
You must be signed in to change notification settings - Fork 231
Use the Fetch API instead of SuperAgent to communicate with MS Graph #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Requests are now processed using the fetch API Response Handler needs some refactoring to handle the error vs bad response
"@types/mocha": "^2.2.34", | ||
"@types/node": "^9.4.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cannot successfully build this library without node typings for require statements
First off, thank you @lahuey for taking the time to propose this change. This makes sense to me. I apologize as I can't get to review this right now. We will definitely take a look at this when we get back to this repo. Solid. |
package.json
Outdated
"browserify": "^13.1.0", | ||
"mocha": "^3.2.0", | ||
"typescript": "^2.2.1" | ||
"typescript": "^2.2.1", | ||
"whatwg-fetch": "^2.0.3" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Global: we should be using an isomorphic Fetch library so that we are covered in the browser and from Node. Consider the following:
spec/core/responseHandling.ts
Outdated
a: 1 | ||
} | ||
}; | ||
const _200_SUPERAGENT_RES_BODY: any = { a: 1 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Global: Remove references to superagent. Change to Fetch, or leave it out all together.
spec/core/responseHandling.ts
Outdated
|
||
const error: Error = new Error(); | ||
(error as any).statusCode = 404; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were you able to run the tests? I wasn't able to from your fork. I then updated to use cross-fetch - two of the tests aren't passing.
27 passing (19ms)
2 failing
1) #ParseResponse() extracts code and request-id from the JSON body of 500 errors:
TypeError: Cannot read property 'code' of null
at lib\spec\core\responseHandling.js:38:29
at Function.ResponseHandler.init (lib\src\ResponseHandler.js:8:13)
at Context.<anonymous> (lib\spec\core\responseHandling.js:37:43)
2) #ParseError() parses a 404 superagent error:
AssertionError: -1 == 404
+ expected - actual
--1
+404
at lib\spec\core\responseHandling.js:52:20
at Function.ResponseHandler.init (lib\src\ResponseHandler.js:17:17)
at Context.<anonymous> (lib\spec\core\responseHandling.js:51:43)
Switch to isomorphic fetch
Agreed on the comments for isomorphic fetch, and ensuring that the tests pass. |
I updated the base branch to pull into. There are some issues that are popping up when I run Please resolve the merge conflicts and we should be good. |
src/GraphRequest.ts
Outdated
@@ -199,38 +199,40 @@ export class GraphRequest { | |||
|
|||
delete(callback?:GraphRequestCallback):Promise<any> { | |||
let url = this.buildFullUrl(); | |||
return this.sendRequestAndRouteResponse(request.del(url), callback) | |||
return this.sendRequestAndRouteResponse( | |||
new Request(url, { method: RequestMethod.DELETE, headers: new Headers() }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We aren't passing in the headers set by the developer. We are always setting the headers collection to an empty collection. We should set the headers passed in by the user and only set an empty header collection if it is a required argument.
For DELETE, I think we should not have a default header.
The headers are set on this._headers. We should check that first for headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are always headers present
headers.append('Authorization', 'Bearer ' + accessToken);
headers.append('SdkVersion', "graph-js-" + packageInfo.version);
src/GraphRequest.ts
Outdated
request | ||
.patch(url) | ||
.send(content), | ||
new Request(url, { method: RequestMethod.PATCH, body: content, headers: new Headers() }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We aren't passing in the headers set by the developer. We are always setting the headers collection to an empty collection. We should set the headers passed in by the user and only set an empty header collection if it is a required argument.
For PATCH, I think we should have a default content-type: application\json header set if no headers are provided by the customer.
src/GraphRequest.ts
Outdated
.post(url) | ||
.send(content), | ||
callback | ||
new Request(url, { method: RequestMethod.POST, body: content, headers: new Headers() }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We aren't passing in the headers set by the developer. We are always setting the headers collection to an empty collection. We should set the headers passed in by the user and only set an empty header collection if it is a required argument.
For POST, I think we should have a default content-type: application\json header set if no headers are provided by the customer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sound good to me
src/GraphRequest.ts
Outdated
{ | ||
method: RequestMethod.PUT, | ||
body: content, | ||
headers: new Headers({ 'Content-Type' : 'application/octet-stream' }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same notes as for the other verbs. We shouldn't set the default content-type to application/octet-stream. We have many other PUT scenarios that use different content types.
https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/profilephoto_update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MIchaelMainer wouldn't this be a breaking change? Isn't the original code setting this header?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shoot. Yes, you're right. This would be breaking. Unfortunately, this implementation is wrong. We can Put other content types in other calls plus, there is a PutStream function that also hard codes this content type. For now, we should leave this broke (not happy about this).
Example
https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/team_put_teams
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lahuey Can you make it so that when the customer sets the content-type header, it checks whether it exists and it removes the existing one if it does. That way, we won't break existing customers who have taken a dependency on this behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed this.configureRequest to use Headers.set instead of Headers.append
@lahuey can you please pull below commit into your branch. It fixes the non get calls. commit: 574974a I tried to push it into your branch, but it is giving me permission denied. This commit is reviewed by @MIchaelMainer |
Changed [string] to string[], fixed spacing, fixed double parens
@bullsseye I added you as a collaborator so you should be able to push now. Sorry about that! |
@lahuey I am using the below command to push the commit: 574974a but it is still giving me permission denied. command: git push https://github.com/lahuey/msgraph-sdk-javascript fix-POST-PATCH-PUT-request:RemoveSuperAgentDependency error that I receive: To https://github.com/lahuey/msgraph-sdk-javascript where fix-POST-PATCH-PUT-request is my local created out of your pull request on which this commit: 574974a is created. Please let me know if I need to do something different to push this. Other way is that you pull this branch: https://github.com/microsoftgraph/msgraph-sdk-javascript/commits/fix-POST-PATCH-PUT-request into your local and then push that into this pull request. This branch is Master + Your pull request + fix commit |
…om U-FAREAST\ramgupt
@bullsseye just merged your changes into my branch |
@MIchaelMainer Please review this commit: 584c60f It includes the test cases that are added to verify this pull request |
@MIchaelMainer Comments are fixed in the commit: 60270db |
@bullsseye Reviewed 60270db, added a comment about where to add the access token. I also added statements for the test assumptions. I think that stating those assumptions are optional, but beneficial. |
@MIchaelMainer I have fixed the comments in this commit 946253f |
👍 Please pull it |
@bullsseye Awesome. Just pushed the commit manually again (Need to figure out how to use GitHub at some point) |
this.urlComponents.version, | ||
this.urlComponents.path]) | ||
+ this.createQueryString(); | ||
this.urlComponents.version, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
previous indentation was correct. Not a blocker though
); | ||
} | ||
|
||
|
||
// Given the built SuperAgentRequest, get an auth token from the authProvider, make the request and return a promise | ||
private routeResponseToPromise(requestBuilder:request.SuperAgentRequest) { | ||
private routeResponseToPromise(request: Request) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the above comment : not a blocker
@@ -271,12 +284,17 @@ export class GraphRequest { | |||
} | |||
|
|||
// Given the built SuperAgentRequest, get an auth token from the authProvider, make the request and invoke the callback | |||
private routeResponseToCallback(requestBuilder:request.SuperAgentRequest, callback: GraphRequestCallback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the above comment: not a blocker
Merging this, There are non blocker changes required on this. |
This is really great! Any idea when we can expect a release with these changes? |
MS Graph JS SDK should break the dependency on SuperAgent
MS Graph SDK is currently using SuperAgent behind the scenes to communicate with the Microsoft Graph. This dependency should be reconsidered for the following reasons:
SuperAgent is using XHR behind the scenes.
While there isn’t anything inherently wrong with XHR, usage of this technology has been “deprecated” for the Fetch API (https://blogs.windows.com/msedgedev/2016/05/24/fetch-and-xhr-limitations/ for more information). Switching to the Fetch API would align MSGraph SDK with the industry standard method for making network requests.
SuperAgent + it’s dependencies is large.
A quick look at graph-js-sdk-web.js reveals that SuperAgent is a large majority of the file’s contents and is only being used to make XHR calls. The Fetch API polyfill is much smaller and will likely simplify the code used to make network requests to Microsoft Graph in the SDK.
Additional "Bug"
Setting the responseType to Document will result in JSON being returned.
Fetch API doesn't support this feature (whatwg/fetch#16) This return type doesn't really make sense for communicating with Microsoft Graph.