Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Updating request library to mimic fetch API #261

Merged
merged 13 commits into from
Feb 10, 2017

Conversation

rorticus
Copy link
Contributor

@rorticus rorticus commented Jan 6, 2017

This PR updates the request APIs to mimic the fetch APIs, which makes it possible to do cool stuff like look at the response headers before the body is downloaded.

This also introduces an event based Response object that can be used to monitor the download progress and send responses to streams (a helper utility for that will be provided in dojo-streams).

Issue: #253

@codecov-io
Copy link

codecov-io commented Jan 9, 2017

Codecov Report

Merging #261 into master will decrease coverage by -1.64%.

@@           Coverage Diff            @@
##           master   #261      +/-   ##
========================================
- Coverage   95.63%    94%   -1.64%     
========================================
  Files          34     37       +3     
  Lines        1900   2167     +267     
  Branches      373    410      +37     
========================================
+ Hits         1817   2037     +220     
- Misses         25     52      +27     
- Partials       58     78      +20
Impacted Files Coverage Δ
src/text.ts 82.75% <100%> (+0.3%)
src/has.ts 100% <100%> (ø)
src/QueuingEvented.ts 100% <100%> (ø)
src/request/util.ts 66.66% <33.33%> (-22.23%)
src/request/Headers.ts 76.92% <76.92%> (ø)
src/request/Response.ts 81.81% <81.81%> (ø)
src/request/TimeoutError.ts 85.71% <85.71%> (ø)
src/request/providers/xhr.ts 88.27% <88.27%> (ø)
src/request/providers/node.ts 89.1% <89.1%> (ø)
src/request/ProviderRegistry.ts 92.85% <92.85%> (ø)
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a4793c9...724b046. Read the comment docs.


return super.register(entryTest, value, first);
const request: {
Copy link
Contributor

@rishson rishson Jan 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why we don't also support OPTIONS and HEAD? At the moment we support a list that is neither the CORS safelist of verbs or the verbs subject to normalization in the fetch spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a good reason that I know of 😄 You can still still make a custom request with whatever method you want, but adding OPTIONS and HEAD should be fairly trivial, so we can do that too!

Copy link
Contributor

@rishson rishson Jan 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, given we actually normalize, e.g. send POST for a post(), then probably best we support all the verbs that spec recommends normalization for. As you say, nothing to stop them doing a custom request for post or pOsT..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥
TVM!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original reason was likely based on what was done in Dojo 1, fwiw. :)

Copy link
Member

@dylans dylans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm ok with this... should have others review as there's a good risk of it causing breaking changes.

@agubler
Copy link
Member

agubler commented Jan 31, 2017

I don't think we have anything dojo 2 using request, so i'm also okay with the changes. See you've asked for a review from @bryanforbes, that's probably a good idea 👍

}

const { limit: redirectLimit = DEFAULT_REDIRECT_LIMIT } = options.redirectOptions;
const { count: redirectCount = 0 } = options.redirectOptions;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be clearer and/or more efficient to format these two lines as such?

const {
    limit: redirectLimit = DEFAULT_REDIRECT_LIMIT,
    count: redirectCount = 0
} = options.redirectOptions;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated!

@@ -1,334 +0,0 @@
import Task from '../async/Task';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order for git to recognize the move of this file, it should be moved in one commit and changed in another. I would recommend rewriting history in this branch to add a commit before starting that moves files into place before making changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So.. I played around with a few ways to get git to recognize this as a rename rather than a new file. I think that it worked.. but it dawned on me that since we only squash from github, that special 'renaming commit' will get squashed into the other commits and we'd lose that history anyways, ending up with a single "'delete xyz', 'add xyy'" flow with files so different that git won't think they are a rename (the problem we have now).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right. Then you can safely ignore me.

response.status < 400
) {
const redirectOptions = options.redirectOptions || {};
const newOptions = Object.create(options);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates a shallow copy of options, so assigning to a sub-object (as is being done on line 227 above) could potentially modify the original. Since no such function exists in @dojo/core to do a deep create, we should create a PR for one and use it here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would we not just use deepAssign({}, options)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go with that @agubler

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deepAssign({}, options) would also work. I figured there was a reason the code was using Object.create() instead of Object.assign(), so to keep the code somewhat the same, I was noting that we don't have the Object.create() counterpart in @dojo/lang. Once you start iterating over properties, you may as well use deepAssign() anyway.


const sanitizedUrl = urlUtil.format(parsedUrl);

error.message = '[' + requestOptions.method + ' ' + sanitizedUrl + '] ' + error.message;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there cases where setting error.message would throw?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but either way we're throwing an error. I could swallow errors to error.message and just ignore it if it didn't work? What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really not sure what the best practice is here. At this point, it might be best to just leave this and if we hit this in reality (rather than trying to cover every potential case), we can adjust.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Let's ignore this for now.

function noop () {}

function setOnError(request: XMLHttpRequest, reject: Function) {
request.onerror = function (event) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this use addEventListener()?

options.method = 'GET';
}

if ((!options.user || !options.password) && options.auth) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reasoning behind allowing two ways to pass authentication information?

const task = new Task<XMLHttpRequest>((resolve, reject) => {
timeoutReject = reject;

request.onprogress = function (event: any) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only handles download progress. It would be nice (perhaps in another PR) to handle upload progress as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

request.open(options.method, requestUrl, !options.blockMainThread, options.user, options.password);

if (has('filereader') && has('blob')) {
request.responseType = 'blob';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be set before calling request.open()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been addressed!

@@ -0,0 +1,67 @@
import Evented from './Evented';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some documentation to this class about what it does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added!

Copy link
Member

@bryanforbes bryanforbes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@rorticus rorticus merged commit 5d21060 into dojo:master Feb 10, 2017
@rorticus rorticus mentioned this pull request Feb 10, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants