import { AxiosRequestConfig } from "axios" ; import { sign } from "aws4" ; import buildUrl from "axios/lib/helpers/buildURL" ; import combineURLs from "axios/lib/helpers/combineURLs" ; import isAbsoluteURL from "axios/lib/helpers/isAbsoluteURL" ; import { SimpleCredentialsProvider } from "./credentials/simpleCredentialsProvider" ; import { AssumeRoleCredentialsProvider } from "./credentials/assumeRoleCredentialsProvider" ; import { CredentialsProvider } from "." ; import { isCredentialsProvider } from "./credentials/isCredentialsProvider" ; export interface InterceptorOptions { /**
     * Target service. Will use default aws4 behavior if not given.
     */ service ? : string ; /**
     * AWS region name. Will use default aws4 behavior if not given.
     */ region ? : string ; /**
     * Whether to sign query instead of adding Authorization header. Default to false.
     */ signQuery ? : boolean ; /**
     * ARN of the IAM Role to be assumed to get the credentials from.
     * The credentials will be cached and automatically refreshed as needed.
     * Will not be used if credentials are provided.
     */ assumeRoleArn ? : string ; /**
     * Number of seconds before the assumed Role expiration
     * to invalidate the cache.
     * Used only if assumeRoleArn is provided.
     */ assumedRoleExpirationMarginSec ? : number ; } export interface SigningOptions { host ? : string ; headers ? : unknown ; path ? : string ; body ? : unknown ; region ? : string ; service ? : string ; signQuery ? : boolean ; method ? : string ; } export interface Credentials { accessKeyId : string ; secretAccessKey : string ; sessionToken ? : string ; } example param options param credentials export const aws4Interceptor = ( options ? , credentials ? ) : ( ( config : AxiosRequestConfig ) => Promise < AxiosRequestConfig > ) => { let credentialsProvider ; if ( isCredentialsProvider ( credentials ) ) { credentialsProvider = credentials ; } else if ( options ?. assumeRoleArn && ! credentials ) { credentialsProvider = new AssumeRoleCredentialsProvider ( { roleArn : options . assumeRoleArn , region : options . region , expirationMarginSec : options . assumedRoleExpirationMarginSec , } ) ; } else { credentialsProvider = new SimpleCredentialsProvider ( credentials ) ; } return async ( config ) : Promise < AxiosRequestConfig > => { if ( ! config . url ) { throw new Error ( "No URL present in request config, unable to sign request" ) ; } if ( config . params ) { config . url = buildUrl ( config . url , config . params , config . paramsSerializer ) ; delete config . params ; } let url = config . url ; if ( config . baseURL && ! isAbsoluteURL ( config . url ) ) { url = combineURLs ( config . baseURL , config . url ) ; } const { host , pathname , search } = new URL ( url ) ; const { data , headers , method } = config ; const transformRequest = getTransformer ( config ) ; const transformedData = transformRequest ( data , headers ) ; const { common , delete : _delete , get , head , post , put , patch , ... headersToSign } = headers ; const signingOptions = { method : method && method . toUpperCase ( ) , host , path : pathname + search , region : options ?. region , service : options ?. service , signQuery : options ?. signQuery , body : transformedData , headers : headersToSign , } ; const resolvedCredentials = await credentialsProvider . getCredentials ( ) ; sign ( signingOptions , resolvedCredentials ) ; config . headers = signingOptions . headers ; if ( signingOptions . signQuery ) { const originalUrl = new URL ( config . url ) ; const signedUrl = new URL ( originalUrl . origin + signingOptions . path ) ; config . url = signedUrl . toString ( ) ; } return config ; } ; } ; const getTransformer = ( config ) => { const { transformRequest } = config ; if ( transformRequest ) { if ( typeof transformRequest === "function" ) { return transformRequest ; } else if ( transformRequest . length ) { return transformRequest [ 0 ] ; } } throw new Error ( "Could not get default transformRequest function from Axios defaults" ) ; } ;