Skip to content
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

fix(:bug:): support use in Node.js with custom fetch (and no global) #264

Merged
merged 7 commits into from
Aug 8, 2018

Conversation

jgravois
Copy link
Contributor

@jgravois jgravois commented Aug 1, 2018

this tweak allows Node.js users to provide their own custom implementation of fetch to request() without polyfilling the global.

AFFECTS PACKAGES:
@esri/arcgis-rest-request

ISSUES CLOSED: #203

AFFECTS PACKAGES:
@esri/arcgis-rest-request

ISSUES CLOSED: #203
@coveralls
Copy link

coveralls commented Aug 1, 2018

Coverage Status

Coverage remained the same at 100.0% when pulling 15e80a1 on custom-fetch-node into 98f7b34 on custom-fetch-headers.

Copy link
Member

@tomwayson tomwayson left a comment

Choose a reason for hiding this comment

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

I don't think the logic is correct here. I tried using node-fetch in the batch geocode demo and I get the following error:

Error: `arcgis-rest-request` requires global variables for `fetch`, `Promise` and `FormData` to be present in the global scope. You are missing `fetch`. We recommend installing the `isomorphic-fetch` modules at the root of your application to add these to the global scope. See https://bit.ly/2KNwWaJ for more info.
    at Object.request (/Users/tom6947/code/arcgis-rest-js/packages/arcgis-rest-request/dist/node/request.js:70:15)
    at bulkGeocode (/Users/tom6947/code/arcgis-rest-js/packages/arcgis-rest-geocoder/dist/node/bulk.js:42:34)
    at chunks.map.chunk (/Users/tom6947/code/arcgis-rest-js/demos/batch-geocoder-node/batch-geocode.js:94:7)
    at Array.map (<anonymous>)
    at parseCsv.then.data (/Users/tom6947/code/arcgis-rest-js/demos/batch-geocoder-node/batch-geocode.js:93:29)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

Also, I think that we need to change this line if (!options.fetch || !Promise || !FormData) { to if (missingGlobals.length > 0) {. I tried that locally on this branch, and it didn't change the above error (options.fetch is successfully passed in). I don't have time right now to fully debug, but I'll look later today.

@tomwayson
Copy link
Member

ok, after digging a little deeper, I think the issue is that even when I supply a valid fetch implementation the the call to bulkGeocode(), which in turn passes that to request(), request() then calls authentication.getToken(url) and there is no way to pass options.fetch to that. If I console.log('options.fetch missing:', !options.fetch); right above this line, I see:

options.fetch missing: false
options.fetch missing: true

I suppose we could have getToken() accept an optional second argument that is either a fetch implementation, or a subset of IRequestOptions - importantly w/o authentication so that we don't create an infinite loop.

@tomwayson
Copy link
Member

I'm thinking that the second parameter should be an options hash instead of just fetch() - unless we're sure that we're not ever going to need to pass any of the other options.

Given that getToken() ultimately calls the generateToken REST endpoint, and given that it's apparently possible to send that via GET, it looks like we'll ultimately need to support at least httpMethod, but I don't think we'll need his tagalong friend maxUrlLength and I don't know if we want to open the door to params.

We don't have to add any other options other than fetch at this time, I'm just suggesting it should be options instead of just fetch().

@jgravois
Copy link
Contributor Author

jgravois commented Aug 7, 2018

I'm just suggesting it should be options instead of just fetch().

i agree.

AFFECTS PACKAGES:
@esri/arcgis-rest-auth
@esri/arcgis-rest-request
batch-geocoder
Copy link
Member

@tomwayson tomwayson left a comment

Choose a reason for hiding this comment

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

Getting there, but, I don't think we should allow passing a full IRequestOptions - b/c if someone supplies an authentication it should go into an endless loop right? For now I'd make a new IGetTokenOptions w/ just fetch and httpMethod and then have IRequestOptions extend that.

@jgravois
Copy link
Contributor Author

jgravois commented Aug 7, 2018

if someone supplies an authentication it should go into an endless loop right?

💡
👦

i've pushed up a few more commits to make the correction.

Copy link
Member

@tomwayson tomwayson left a comment

Choose a reason for hiding this comment

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

Man, I was this close to approving and merging, but one final pass over reveled the breaking change :(

@@ -19,18 +14,18 @@ export interface IGenerateTokenResponse {

export function generateToken(
url: string,
params: IGenerateTokenParams
requestOptions: IGenerateTokenRequestOptions
Copy link
Member

Choose a reason for hiding this comment

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

This is a breaking change and I really don't want to get all wrapped up in that right now. Maybe we can avoid that by making this requestOptionsOrParams: (IGenerateTokenRequestOptions | IGenerateTokenParams) and then internally setting:

// TODO: remove this next breaking change and just have this take IGenerateTokenRequestOptions
const requestOptions = requestOptionsOrParams.params ? requestOptionsOrParams : { params: requestOptionsOrParams };

and then add this to #137

I know that's yucky, but feels better than dealing w/ a breaking change right now.

Copy link
Contributor Author

@jgravois jgravois Aug 7, 2018

Choose a reason for hiding this comment

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

i agree that a union type here is yucky and i also agree that its preferable to introducing a breaking change.

just pushed up a commit that uses a type guard because TS likes to make ternary operators even less readable.

@jgravois jgravois mentioned this pull request Aug 7, 2018
35 tasks
Copy link
Member

@tomwayson tomwayson left a comment

Choose a reason for hiding this comment

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

🎉

…nSession methods

AFFECTS PACKAGES:
@esri/arcgis-rest-auth
@esri/arcgis-rest-request
refactor: allow passing a custom fetch through for ApplicationSession too
@jgravois jgravois merged commit a008663 into custom-fetch-headers Aug 8, 2018
@jgravois jgravois deleted the custom-fetch-node branch August 8, 2018 00:18
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants