-
Notifications
You must be signed in to change notification settings - Fork 211
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
requestOptions accepting function so that we can change options depending on the request #381
base: master
Are you sure you want to change the base?
Conversation
@dinumathai Thank you for this contribution! I generally like the idea of this PR. Giving full control over the requests that the resolvers make will make OtG more usable and gives more options to users. However, I wonder if we should in a different way. I will give some background. In the beginning, there was only the Another user also requested the programmatically control request headers so we modified I do not want to add new request options (I would like to deprecate Before: export type RequestHeadersFunction<TSource, TContext, TArgs> = (
method: string,
path: string,
title: string,
resolverParams?: {
source: TSource
args: TArgs
context: TContext
info: GraphQLResolveInfo
}
) => Headers
export declare type RequestURLFunction<TSource, TContext, TArgs> = (
method: string,
path: string,
title: string,
resolverParams?: {
source: TSource;
args: TArgs;
context: TContext;
info: GraphQLResolveInfo;
}) => string;
export type RequestOptions<TSource, TContext, TArgs> = Omit<
NodeRequest.OptionsWithUrl,
'headers'
> & {
headers?: Headers | RequestHeadersFunction<TSource, TContext, TArgs>
}
// Has `headers`, `qs`, and `urlResolver`
// Has awkward `requestOptions` with modified `headers` field
export type InternalOptions<TSource, TContext, TArgs> = {
...
headers?: Headers | RequestHeadersFunction<TSource, TContext, TArgs>
qs?: { [key: string]: string }
urlResolver?: RequestURLFunction<TSource, TContext, TArgs>
requestOptions?: Partial<RequestOptions<TSource, TContext, TArgs>>
...
} After: export type RequestOptionsFunction<TSource, TContext, TArgs> = (
method: string,
path: string,
title: string,
resolverParams?: {
source: TSource
args: TArgs
context: TContext
info: GraphQLResolveInfo
}
) => Partial<NodeRequest.OptionsWithUrl>
// Deprecated `headers` and `qs`
// requestOptions is an object or a function
// if `url` or `headers` is changed, then request will reflect those changes
export type InternalOptions<TSource, TContext, TArgs> = {
...
requestOptions: Partial<NodeRequest.OptionsWithUrl> | RequestOptionsFunction<TSource, TContext, TArgs>
...
} Does this make sense? What do you think? |
That is a better solution. But do we need to keep Also we need to think of replacing the deprecated package "request". |
I am fine with making breaking changes as long as they are released in a major version and it is properly documented. However, I do have a few concerns about this change. Currently, we perform an Perhaps we should also consider adding a new option, like I'm concerned that there may be a third case. The I also wonder if we should add a new option like Currently, we are using the request module to perform our API calls. However, the module has been long deprecated and we need to use a new library. There is a PR for it #315 (as well as related #268). Until we find a solution for this, I hesitate to make very drastic changes. Therefore, I do not think we should remove What do you think? |
Just wanted to put one more option for consideration. Shall we pass "options" as a parameter to the RequestOptionsFunction. This way developer will have more control. But we will need to validate for
|
de8a916
to
ad23d59
Compare
@Alan-Cha, Added RequestOptionsFunction. Please review, and let me know the changes needed. Feel free to make any changes. |
ad23d59
to
fa6f0ac
Compare
…ding on the request Signed-off-by: Dinu Mathai <[email protected]>
fa6f0ac
to
0b0f8e7
Compare
Signed-off-by: Alan Cha <[email protected]>
6363749
to
4d478ab
Compare
Yes, this is a great idea. I was also thinking of this. @dinumathai I made a large number of changes, including restructuring the There is a complication that has come up that I wasn't aware of. This is a note that I have added to the
First, let me know if this makes any sense to you. Secondly, I just want to point out that this has always been a problem, for example with using the Maybe there should be two different functions, one that is used for I hope this all makes sense. If it's not intuitive, that is exactly why this is a big issue. |
@@ -11,26 +11,31 @@ import { RequestOptions } from './types/options'; | |||
import { GraphQLFieldResolver } from 'graphql'; | |||
import { IncomingHttpHeaders } from 'http'; | |||
export declare const OPENAPI_TO_GRAPHQL = "_openAPIToGraphQL"; | |||
declare type GetResolverParams<TSource, TContext, TArgs> = { | |||
declare type GetSubscribeParams<TSource, TContext, TArgs> = { |
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.
Just cleaning up old code. Just ignore.
@@ -97,7 +131,7 @@ export declare type InternalOptions<TSource, TContext, TArgs> = { | |||
* into a GraphQL ID type. To allow for more customzation, this option allows | |||
* users to specify other formats that should be interpreted as ID types. | |||
*/ | |||
idFormats?: string[]; | |||
idFormats: string[]; |
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.
More clean up.
} | ||
} | ||
// The options `requestOptions` will finalize the options | ||
if (requestOptions) { |
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.
requestOptions
has been moved to the very bottom, right before the call. This allows requestOptions
to have the final say on how the request should be made.
Signed-off-by: Alan Cha <[email protected]>
path, | ||
title, | ||
{ source, args, context, info }, | ||
options |
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.
This is where we also provide the generated Request options as you suggested.
} else { | ||
const oauthHeader = createOAuthHeader(data, context) | ||
Object.assign(options.headers, oauthHeader) | ||
options = merge(options, requestOptionsValue) |
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.
Notice that we merge the original options with requestOptionsValue
. If we were to implement a requestOptionsStrict
option like I mentioned previously, if would do something here.
* provided through the options | ||
*/ | ||
function skipArg<TSource, TContext, TArgs>( | ||
function shouldSkipArgumentBecauseOptions<TSource, TContext, TArgs>( |
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.
This is where the problem I mentioned before comes from.
getResolver
in resolver_builder.ts
uses requestOptions
to change the API call.
shouldSkipArgumentBecauseOptions
in schema_builder.ts
uses requestOptions
to determine if it should add an argument to the field in the GraphQL
They both provide different arguments.
*/ | ||
const requestOptionsValue = | ||
typeof requestOptions === 'function' | ||
? requestOptions( |
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.
Here we provide method
, path
, title
, resolver arguments, and generated options
typeof data.options.requestOptions === 'object' | ||
? data.options.requestOptions | ||
: typeof data.options.requestOptions === 'function' | ||
? data.options.requestOptions( |
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.
Here we only provide method
, path
, and title
. No resolver arguments or generated request options.
headers: (method, path, title) => { | ||
if (method === 'get' && path === '/snack') { | ||
return { | ||
requestOptions: (method, path, title) => { |
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.
Example of using requestOptions as a function.
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.
Looks good. Thank you.
Planned any date for merge ? |
@dinumathai I have a lot of concerns about whether this is the right design. As I mentioned previously, |
Only solution I can think of is - Update README - explaining about this. |
Or shall we move back to initial option of adding new parameter ? |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
1 similar comment
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
16 similar comments
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@dinumathai: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
What is this change ?
Added urlResolver on Resolver options, so that we can change the URL for api call depending on the request context.
Why Is this change ?
To pull data from multiple api which is having the similar signature, depending on a value from the request header.