All files / api common.ts

100% Statements 28/28
100% Branches 6/6
100% Functions 8/8
100% Lines 24/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112                                                  9x       9x   12x 12x     9x     7x               9x       3x 3x 3x               12x 12x             9x   7x   7x 7x 7x                               9x     16x   16x   5x     11x         7x       7x    
/**
 * @license
 * Copyright 2019 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
import { FirebaseError } from '@firebase/util';
import { GenerateAuthTokenResponse } from '../interfaces/api-response';
import { AppConfig } from '../interfaces/app-config';
import {
  CompletedAuthToken,
  RegisteredInstallationEntry,
  RequestStatus
} from '../interfaces/installation-entry';
import {
  INSTALLATIONS_API_URL,
  INTERNAL_AUTH_VERSION
} from '../util/constants';
import { ERROR_FACTORY, ErrorCode } from '../util/errors';
 
export function getInstallationsEndpoint({ projectId }: AppConfig): string {
  return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;
}
 
export function extractAuthTokenInfoFromResponse(
  response: GenerateAuthTokenResponse
): CompletedAuthToken {
  return {
    token: response.token,
    requestStatus: RequestStatus.COMPLETED,
    expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),
    creationTime: Date.now()
  };
}
 
export async function getErrorFromResponse(
  requestName: string,
  response: Response
): Promise<FirebaseError> {
  const responseJson: ErrorResponse = await response.json();
  const errorData = responseJson.error;
  return ERROR_FACTORY.create(ErrorCode.REQUEST_FAILED, {
    requestName,
    serverCode: errorData.code,
    serverMessage: errorData.message,
    serverStatus: errorData.status
  });
}
 
export function getHeaders({ apiKey }: AppConfig): Headers {
  return new Headers({
    'Content-Type': 'application/json',
    Accept: 'application/json',
    'x-goog-api-key': apiKey
  });
}
 
export function getHeadersWithAuth(
  appConfig: AppConfig,
  { refreshToken }: RegisteredInstallationEntry
): Headers {
  const headers = getHeaders(appConfig);
  headers.append('Authorization', getAuthorizationHeader(refreshToken));
  return headers;
}
 
export interface ErrorResponse {
  error: {
    code: number;
    message: string;
    status: string;
  };
}
 
/**
 * Calls the passed in fetch wrapper and returns the response.
 * If the returned response has a status of 5xx, re-runs the function once and
 * returns the response.
 */
export async function retryIfServerError(
  fn: () => Promise<Response>
): Promise<Response> {
  const result = await fn();
 
  if (result.status >= 500 && result.status < 600) {
    // Internal Server Error. Retry request.
    return fn();
  }
 
  return result;
}
 
function getExpiresInFromResponseExpiresIn(responseExpiresIn: string): number {
  // This works because the server will never respond with fractions of a second.
  return Number(responseExpiresIn.replace('s', '000'));
}
 
function getAuthorizationHeader(refreshToken: string): string {
  return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;
}