'How can I add customised header on http request for authentication when using flutter graphql library?

I am using this library https://pub.dev/packages/graphql_flutter for graphql in a flutter web application. Below code can be used to get authentication token:

import 'package:graphql_flutter/graphql_flutter.dart';
final HttpLink httpLink = HttpLink(
    'https://api.github.com/graphql',
  );

  final AuthLink authLink = AuthLink(
    getToken: () async => 'Bearer <YOUR_PERSONAL_ACCESS_TOKEN>',
    // OR
    // getToken: () => 'Bearer <YOUR_PERSONAL_ACCESS_TOKEN>',
  );

but how can I put the token in the http header like x-api-key: xxxx when sending requests?

I have tried:

HttpLink link = HttpLink(
    uri: 'https://api.github.com/graphql',
    headers: <String, String>{
      'x-api-key': 'xxxx',
    },
  );

but it gives me the error: The named parameter 'uri' isn't defined. Try correcting the name to an existing named parameter's name, or defining a named parameter with the name 'uri'.



Solution 1:[1]

Update: base on the answer from @Moaid

import 'package:graphql_flutter/graphql_flutter.dart';

typedef GetHeaders = FutureOr<Map<String, String>> Function();

class CustomAuthLink extends Link {
  CustomAuthLink({
    this.getHeaders,
  });

  final GetHeaders getHeaders;

  @override
  Stream<Response> request(Request request, [NextLink forward]) {
    StreamController<Response> controller;
    Future<void> onListen() async {
      try {
        final Map<String, String> headers = await getHeaders();

        return request.updateContextEntry<HttpLinkHeaders>(
          (_headers) => HttpLinkHeaders(
            headers: <String, String>{
              ...headers,
            },
          ),
        );
      } catch (error) {
        controller.addError(error);
      }

      await controller.addStream(forward(request));
      await controller.close();
    }

    controller = StreamController<Response>(onListen: onListen);

    return controller.stream;
  }
}

Solution 2:[2]

Base on the answer from @moaid-alrazhy and after checking how AuthLink is working

class CustomAuthLink extends Link {
  CustomAuthLink();

  @override
  Stream<Response> request(Request request, [NextLink? forward]) async* {
    // Some logic here
    final AuthService authService = GetIt.I.get<AuthService>();

    final String? token = authService.token;
    final String deviceID = await DeviceInformation.deviceIMEINumber;

    // TIP: do not forget getting new Request instance!
    final Request req = request.updateContextEntry<HttpLinkHeaders>(
      (HttpLinkHeaders? headers) => HttpLinkHeaders(
        headers: <String, String>{
          // put oldest headers
          ...headers?.headers ?? <String, String>{},
          // and add a new headers
          'Authorization': 'Bearer $token',
          'x-device-id': deviceID,
        },
      ),
    );

    // and "return" new Request with updated headers
    yield* forward!(req);
  }
}

Solution 3:[3]

you can add it to your HttpLink like this

HttpLink link = HttpLink(
    'https://api.github.com/graphql',
    headers: <String, String>{
      'x-api-key': 'xxxx',
    },
  );

however this was in old versions .. now for more headers your have to write your own CustomAuthLink like

typedef GetHeaders = Future<Map<String, String>> Function();

class CustomAuthLink extends Link {
  CustomAuthLink({
    this.getHeaders,
  }) : super(
          request: (Operation operation, [NextLink forward]) {
            StreamController<FetchResult> controller;

            Future<void> onListen() async {
              try {
                final Map<String, String> headers = await getHeaders();

                operation.setContext(<String, Map<String, String>>{
                  'headers': headers
                });
              } catch (error) {
                controller.addError(error);
              }

              await controller.addStream(forward(operation));
              await controller.close();
            }

            controller = StreamController<FetchResult>(onListen: onListen);

            return controller.stream;
          },
        );

  GetHeaders getHeaders;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JerryZhou
Solution 2 WiRight
Solution 3