How can I make Angular Universal with Zone.JS wait for an AWS Lambda SDK invoke call

188 Views Asked by At

I'm using Angular Universal with Zone.JS and until now thought that it was waiting for my API calls to resolve before delivering the response. As I understand it, Zone.JS patches various libraries in order to know when the application has settled and everything is complete.

Our frontend application is running within AWS Lambda and in a Universal context we make other AWS Lambda Apollo GraphQL calls to our API using a custom link.

If I make API calls using the standard HttpClient from @angular/common/http then Universal will wait... but when using aws-sdk with https agent then it does not. I can't for the life of me figure out how to patch it with Zone.

When looking at the Angular HttpClient in Server, I can see references to wrapping xhr2 in Zone but am not sure how I'd do the same using https/aws: https://github.com/angular/angular/blob/master/packages/platform-server/src/http.ts#L27

import { Injectable } from '@angular/core';
import { ApolloLink, Observable } from '@apollo/client/core';
import { AuthService } from '@tma/core';
import AwsLambda from 'aws-sdk/clients/lambda';
import { print } from 'graphql';
import { Agent } from 'https';
import { first } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class ApiLinkLambda extends ApolloLink {
  client = new AwsLambda({
    region: process.env.AWS_REGION,
    httpOptions: {
      agent: new Agent({
        keepAlive: true,
        maxSockets: 50,
        rejectUnauthorized: true,
      }),
    },
  });

  constructor(authService: AuthService) {
    super(operation => {
      return new Observable(observer => {
        authService.token$
          .pipe(first())
          .toPromise()
          .then(token => {
            // Make lambda call
            return this.client
              .invoke({
                FunctionName: 'example-graphqlServer',
                InvocationType: 'RequestResponse',
                Payload: JSON.stringify({
                  body: {
                    query: print(operation.query),
                    variables: operation.variables,
                  },
                  headers: {
                    Authorization: token,
                  },
                  httpMethod: 'POST',
                  path: '/graphql',
                  requestContext: {
                    requestTimeEpoch: Date.now(),
                  },
                }),
              })
              .promise()
              .then(result => {
                const response = JSON.parse(result.Payload!.toString());
                const body = JSON.parse(response.body);
                observer.next(body);
                observer.complete();
              });
          });
      });
    });
  }
}
0

There are 0 best solutions below