or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

AWS SDK Middleware Recursion Detection

Internal AWS SDK middleware that provides recursion detection for Lambda functions by automatically injecting AWS X-Ray trace IDs from environment variables into HTTP request headers. This middleware helps prevent recursive Lambda function invocations by enabling trace-based detection mechanisms.

Package Information

  • Package Name: @aws-sdk/middleware-recursion-detection
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @aws-sdk/middleware-recursion-detection
  • Runtime Support: Node.js >= 18.0.0
  • License: Apache-2.0

Core Imports

import {
  recursionDetectionMiddleware,
  addRecursionDetectionMiddlewareOptions,
  getRecursionDetectionPlugin
} from "@aws-sdk/middleware-recursion-detection";

// Required types from @smithy/types
import type {
  BuildMiddleware,
  BuildHandler,
  BuildHandlerArguments,
  BuildHandlerOutput,
  BuildHandlerOptions,
  AbsoluteLocation,
  Pluggable,
  MetadataBearer,
  MiddlewareStack
} from "@smithy/types";

// Required HTTP types
import type { HttpRequest } from "@smithy/protocol-http";

For CommonJS:

const {
  recursionDetectionMiddleware,
  addRecursionDetectionMiddlewareOptions,
  getRecursionDetectionPlugin
} = require("@aws-sdk/middleware-recursion-detection");

Basic Usage

import { getRecursionDetectionPlugin } from "@aws-sdk/middleware-recursion-detection";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";

// The plugin is typically applied automatically by the AWS SDK
// when running in Lambda environments. Manual usage is rare:
const client = new DynamoDBClient({
  region: "us-east-1"
});

// Manual application (internal AWS SDK usage pattern):
const plugin = getRecursionDetectionPlugin({ runtime: "node" });
plugin.applyToStack(client.middlewareStack);

// Environment variables that activate the middleware:
// - AWS_LAMBDA_FUNCTION_NAME=my-lambda-function  
// - _X_AMZN_TRACE_ID=Root=1-5e1b4151-5ac6c58336eda04f27295b81

Environment Variables

The middleware automatically detects Lambda environments using these environment variables:

  • AWS_LAMBDA_FUNCTION_NAME: Must be present and non-empty to activate middleware
  • _X_AMZN_TRACE_ID: The X-Ray trace ID that gets injected into request headers

Internal Constants

The middleware uses these internal constants (not exported):

  • TRACE_ID_HEADER_NAME = "X-Amzn-Trace-Id" - Standard AWS trace header name
  • ENV_LAMBDA_FUNCTION_NAME = "AWS_LAMBDA_FUNCTION_NAME" - Lambda function name environment variable
  • ENV_TRACE_ID = "_X_AMZN_TRACE_ID" - X-Ray trace ID environment variable

Capabilities

Middleware Factory

Creates the core middleware function that handles trace ID injection.

/**
 * Creates middleware that injects trace ID to request headers for recursion detection in Lambda
 * @param options - Configuration containing runtime information  
 * @returns BuildMiddleware that processes HTTP requests
 * @internal
 */
const recursionDetectionMiddleware: <Output extends MetadataBearer>(
  options: PreviouslyResolved
) => BuildMiddleware<any, Output>;

interface PreviouslyResolved {
  /** Runtime environment (e.g., "node", "browser") */
  runtime: string;
}

Middleware Configuration

Configuration options for adding the middleware to the middleware stack.

/**
 * Configuration options for adding recursion detection middleware to the stack
 * @internal
 */
const addRecursionDetectionMiddlewareOptions: BuildHandlerOptions & AbsoluteLocation;

This constant contains:

  • step: "build" - Middleware runs during the build phase
  • tags: ["RECURSION_DETECTION"] - Tagged for identification
  • name: "recursionDetectionMiddleware" - Middleware name
  • override: true - Can override existing middleware
  • priority: "low" - Low priority in the stack

Plugin Factory

Creates a pluggable middleware that can be applied to client stacks.

/**
 * Creates a pluggable middleware for recursion detection
 * @param options - Configuration containing runtime information
 * @returns Pluggable object with applyToStack method
 * @internal
 */
const getRecursionDetectionPlugin: (
  options: PreviouslyResolved
) => Pluggable<any, any>;

Types

interface PreviouslyResolved {
  runtime: string;
}

interface BuildMiddleware<Input, Output extends MetadataBearer> {
  (next: BuildHandler<Input, Output>, context: any): BuildHandler<Input, Output>;
}

interface BuildHandler<Input, Output extends MetadataBearer> {
  (args: BuildHandlerArguments<Input>): Promise<BuildHandlerOutput<Output>>;
}

interface BuildHandlerArguments<Input> {
  input: Input;
  request: HttpRequest;
}

interface BuildHandlerOutput<Output extends MetadataBearer> {
  output: Output;
  response: any;
}

interface BuildHandlerOptions {
  step: "build" | "serialize" | "finalize" | "deserialize";
  tags: string[];
  name: string;
  override: boolean;
  priority: "high" | "normal" | "low";
}

interface AbsoluteLocation {
  before?: string[];
  after?: string[];
}

interface Pluggable<Input, Output> {
  applyToStack(stack: MiddlewareStack<Input, Output>): void;
}

interface MiddlewareStack<Input, Output> {
  add(
    middleware: BuildMiddleware<Input, Output>, 
    options: BuildHandlerOptions & AbsoluteLocation
  ): void;
  addRelativeTo(
    middleware: BuildMiddleware<Input, Output>,
    options: BuildHandlerOptions & AbsoluteLocation
  ): void;
  concat<InputType, OutputType>(
    from: MiddlewareStack<InputType, OutputType>
  ): MiddlewareStack<InputType | Input, OutputType | Output>;
  resolve<InputType, OutputType>(
    handler: BuildHandler<InputType, OutputType>,
    context: any
  ): BuildHandler<InputType, OutputType>;
}

interface MetadataBearer {
  $metadata: any;
}

interface HttpRequest {
  headers: Record<string, string>;
  static isInstance(request: any): request is HttpRequest;
}

Behavior Details

Runtime Requirements

  • Only operates in Node.js runtime environments (runtime: "node")
  • Skips processing for browser runtime environments
  • Only processes HttpRequest instances

Trace ID Injection Logic

  1. Only operates when runtime is "node" and request is HttpRequest instance
  2. Checks if both AWS_LAMBDA_FUNCTION_NAME and _X_AMZN_TRACE_ID environment variables are present and non-empty
  3. Performs case-insensitive lookup for existing X-Amzn-Trace-Id header in request headers
  4. If no existing trace header found (regardless of case), adds X-Amzn-Trace-Id header with value from _X_AMZN_TRACE_ID
  5. Passes request to next handler in the middleware chain

Header Handling

  • Uses standard header name: X-Amzn-Trace-Id
  • Performs case-insensitive detection of existing headers using Object.keys(request.headers).find(h => h.toLowerCase() === 'x-amzn-trace-id')
  • Preserves existing trace headers to avoid overwriting (even with different casing)
  • Validates both function name and trace ID are non-empty strings before injection

Type Checking

The middleware includes built-in type validation:

  • Only processes requests that pass HttpRequest.isInstance(request) check
  • Validates environment variables using nonEmptyString helper that ensures values are both strings and non-empty
  • Only operates when runtime is explicitly "node" (skips browser and other environments)

Dependencies

The package depends on:

  • @aws-sdk/types: AWS SDK type definitions
  • @smithy/protocol-http: HTTP protocol utilities
  • @smithy/types: Smithy framework types for middleware
  • tslib: TypeScript runtime library

Internal Package Notice

This is an internal AWS SDK package designed for use within the AWS SDK ecosystem. Direct usage by external consumers is not recommended. The middleware is typically applied automatically when using AWS SDK clients in Lambda environments.