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

How do you retrieve headers from the response? #704

Closed
FilledStacks opened this issue Jul 31, 2020 · 11 comments
Closed

How do you retrieve headers from the response? #704

FilledStacks opened this issue Jul 31, 2020 · 11 comments

Comments

@FilledStacks
Copy link

I'm using your GraphQLClient and was wondering how to get the headers from the http response that fetched the information. We have cookies in our header that needs to be written out and re-used in some of our pure http calls outside of the graphQL data requests.

Do you support this functionality? if not can you point me in the direction of where I can look to expose this, I'll fork and use that for now and request a PR as well if you'd like the functionality into the main package.

@vasilich6107
Copy link
Contributor

HttpLink supports overriding client

HttpLink(uri: uri, httpClient: httpClient);

Making your custom client is pretty esasy
just extend
abstract class OOClient extends BaseClient and implement send method.

@FilledStacks
Copy link
Author

Thanks, just to confirm I'm not going in the wrong direction, overriding the send will allow me to access the response of that http request?

@vasilich6107
Copy link
Contributor

Yes. In send you’ll have

final response = await _client.send(request);
Return response;

So you’ll can do whatever you like with response

@micimize
Copy link
Collaborator

micimize commented Aug 6, 2020

v4 will probably have response headers in a gql link context: gql-dart/gql#119

#371 was the previous main thread on this but I think the conclusion is just not pragmatic. The people need their headers. Anyhow I'll probably still leave it for v4

@jeffscaturro-aka
Copy link

jeffscaturro-aka commented Aug 19, 2020

Wanted to chime in here as I found a way to accomplish this by pulling out the response object we stuff into the operation:

https://github.com/zino-app/graphql-flutter/blob/f12aae525b1bf7fd5c3120a3a62bccd87cabad68/packages/graphql/lib/src/link/http/link_http.dart#L90-L100

I have a custom link I created to get access to the operation and fetchResult like:

class GraphQLLink extends Link {
  final Future<void> Function(Operation) onRequest;
  final Future<void> Function(Operation, FetchResult) onResponse;
  final Future<void> Function(Operation, FetchResult) onError;

  GraphQLLink({
    this.onRequest,
    this.onResponse,
    this.onError,
  }) : super(request: (Operation operation, [NextLink forward]) {
          StreamController<FetchResult> controller;

          Future<void> onListen() async {
            if (onRequest != null) {
              await onRequest(operation);
            }

            final stream = forward(operation).asyncMap((fetchResult) async {
              if (fetchResult.errors != null &&
                  fetchResult.errors.isNotEmpty &&
                  onError != null) {
                await onError(operation, fetchResult);
              }

              if (onResponse != null) {
                await onResponse(operation, fetchResult);
              }

              return fetchResult;
            });

            await controller.addStream(stream);
            await controller.close();
          }

          controller = StreamController<FetchResult>(onListen: onListen);
          return controller.stream;
        });
}

Which then enables me to do something like:

...
}, onResponse: (operation, fetchResult) async {
    // Pull the context off of the operation (not the FetchResult as we don't populate it)
    final operationsContext =
        operation.getContext() ?? <String, dynamic>{};

    // Grab the `StreamedResponse` object that was stuffed into the operation.
    final StreamedResponse response = operationsContext['response'];

    // Now we can pull the response headers off that `StreamedResponse`
    final responseHeaders = response?.headers ?? <String, String>{};
...

Hope this helps!

@micimize you may find interest in this solution as it also might be an easy win to include the headers somehow in the parseResponse function over in https://github.com/zino-app/graphql-flutter/blob/master/packages/graphql/lib/src/link/http/link_http.dart#L296.

@micimize micimize mentioned this issue Aug 20, 2020
5 tasks
@micimize
Copy link
Collaborator

@jeffscaturro-aka woah I had forgotten we add the response to the context. Will try and keep that in mind for gql-dart/gql#119 – maybe it really should be the entire response after all

@emme1444
Copy link

@jeffscaturro-aka is there any way to grab anything from the response headers where I make my query/mutation? For instance in the repository where I do my request (using your suggested approach). Something like this:

// repository / service
{
  // ...
  final result = await graphqlClient.mutate(options);

  // here I'd like to store the cookie sent in the response
  // ...
}

If this is not currently possible, would you know if this will be possible in v4? I can't find a way to do so in the v4 beta source, but I might as well be blind.

Or can I somehow use the example you suggested above to add that data (response headers) back in the result? I don't think so, right?

Thanks!

@micimize
Copy link
Collaborator

@emme1444 I think you can get it in the link chain from Context with response.context.entry<HttpLinkResponseContext>().

QueryResult doesn't contain context, but we should add it #793

@emme1444
Copy link

@micimize Thanks for the reply! Yeah okay, so I ended up just forking, adding the context to QueryResult, and overriding that dependency. Thanks for the tip! I'll be looking forward to a new 4 release, hopefully in the near future.

@Henrixounez
Copy link

Thanks @jeffscaturro-aka , simple enough solution and it is working great !

@asim-sansi
Copy link

Anyone working on version 4.0.0-beta or version 4.0.0 you can now get the headers directly from response

_client.mutate(
          MutationOptions(
            document: gql(addMutation.signIn('$_email', '$_password')),
          ),
        ).then((value) => {
              if (value.hasException){
                  print(value.context.entry<HttpLinkResponseContext>().headers['set-cookie'])
                }
              else{
                  print(value.context.entry<HttpLinkResponseContext>().headers['set-cookie']),
                }
            });

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

No branches or pull requests

7 participants