A presigner based on signature V4 that generates signed URLs for Amazon S3 operations
npx @tessl/cli install tessl/npm-aws-sdk--s3-request-presigner@3.879.0The @aws-sdk/s3-request-presigner package provides functionality for generating presigned URLs for Amazon S3 operations. It offers both high-level integration with S3Client and Command objects through the getSignedUrl function, and low-level request presigning through the S3RequestPresigner class.
npm install @aws-sdk/s3-request-presignerimport { getSignedUrl, S3RequestPresigner } from "@aws-sdk/s3-request-presigner";For CommonJS:
const { getSignedUrl, S3RequestPresigner } = require("@aws-sdk/s3-request-presigner");For accessing constants:
import {
UNSIGNED_PAYLOAD,
SHA256_HEADER,
ALGORITHM_QUERY_PARAM
} from "@aws-sdk/s3-request-presigner";import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const client = new S3Client({ region: "us-east-1" });
const command = new GetObjectCommand({
Bucket: "my-bucket",
Key: "my-file.txt"
});
// Generate presigned URL (expires in 15 minutes by default)
const url = await getSignedUrl(client, command, { expiresIn: 3600 });
console.log(url);The presigner is built around two main components:
getSignedUrl function that integrates seamlessly with AWS SDK v3 clients and commandsS3RequestPresigner class for direct HTTP request signing when you need more controlGenerate presigned URLs from S3Client and Command objects with automatic endpoint resolution and authentication.
/**
* Generate a presigned URL from an S3Client and Command
* @param client - S3Client instance
* @param command - S3 command (GetObjectCommand, PutObjectCommand, etc.)
* @param options - Presigning options including expiration and headers
* @returns Promise resolving to the presigned URL string
*/
function getSignedUrl<
InputTypesUnion extends object,
InputType extends InputTypesUnion,
OutputType extends MetadataBearer = MetadataBearer
>(
client: Client<any, InputTypesUnion, MetadataBearer, any>,
command: Command<InputType, OutputType, any, InputTypesUnion, MetadataBearer>,
options?: RequestPresigningArguments
): Promise<string>;Usage Examples:
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
const s3Client = new S3Client({ region: "us-east-1" });
// Get presigned URL for downloading a file
const getCommand = new GetObjectCommand({
Bucket: "my-bucket",
Key: "document.pdf"
});
const downloadUrl = await getSignedUrl(s3Client, getCommand, { expiresIn: 3600 });
// Get presigned URL for uploading a file
const putCommand = new PutObjectCommand({
Bucket: "my-bucket",
Key: "upload.jpg",
ContentType: "image/jpeg"
});
const uploadUrl = await getSignedUrl(s3Client, putCommand, { expiresIn: 1800 });Configure which headers are signed, unsigned, or hoisted for security and compatibility.
// Sign non-x-amz headers and enforce them in requests
const urlWithSignedHeaders = await getSignedUrl(s3Client, command, {
signableHeaders: new Set(["content-type", "content-length"]),
expiresIn: 3600
});
// Force x-amz headers to be present in upload request (cannot be signed)
const urlWithUnhoistableHeaders = await getSignedUrl(s3Client, putCommand, {
unhoistableHeaders: new Set(["x-amz-checksum-sha256"]),
expiresIn: 1800
});
// Allow x-amz-server-side-encryption headers to be hoisted to query string
const urlWithHoistableHeaders = await getSignedUrl(s3Client, sseCommand, {
hoistableHeaders: new Set([
"x-amz-server-side-encryption",
"x-amz-server-side-encryption-aws-kms-key-id"
])
});Direct HTTP request signing for advanced use cases where you need full control over the request.
/**
* Low-level presigner class for signing HTTP requests directly
*/
class S3RequestPresigner {
/**
* Create an S3RequestPresigner instance
* @param options - Configuration options for the presigner
*/
constructor(options: S3RequestPresignerOptions);
/**
* Presign an HTTP request using the configured credentials
* @param requestToSign - HTTP request to presign
* @param options - Presigning options
* @returns Promise resolving to the presigned HTTP request
*/
presign(
requestToSign: IHttpRequest,
options?: RequestPresigningArguments
): Promise<IHttpRequest>;
/**
* Presign an HTTP request using specific credentials (for S3 Express)
* @param requestToSign - HTTP request to presign
* @param credentials - Specific AWS credentials to use
* @param options - Presigning options
* @returns Promise resolving to the presigned HTTP request
*/
presignWithCredentials(
requestToSign: IHttpRequest,
credentials: AwsCredentialIdentity,
options?: RequestPresigningArguments
): Promise<IHttpRequest>;
}Usage Examples:
import { S3RequestPresigner } from "@aws-sdk/s3-request-presigner";
import { S3Client } from "@aws-sdk/client-s3";
import { HttpRequest } from "@smithy/protocol-http";
import { Hash } from "@smithy/hash-node";
import { formatUrl } from "@aws-sdk/util-format-url";
// Create presigner from S3Client configuration
const s3Client = new S3Client({ region: "us-west-2" });
const presigner = new S3RequestPresigner({
...s3Client.config
});
// Or create with explicit configuration
const presigner = new S3RequestPresigner({
region: "us-west-2",
credentials: {
accessKeyId: "AKIAIOSFODNN7EXAMPLE",
secretAccessKey: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
},
sha256: Hash.bind(null, "sha256")
});
// Create and presign HTTP request
const request = new HttpRequest({
method: "GET",
protocol: "https:",
hostname: "my-bucket.s3.us-west-2.amazonaws.com",
path: "/my-file.txt",
headers: {
host: "my-bucket.s3.us-west-2.amazonaws.com"
}
});
const presignedRequest = await presigner.presign(request, { expiresIn: 3600 });
const presignedUrl = formatUrl(presignedRequest);/**
* Configuration options for S3RequestPresigner constructor
* Extends SignatureV4 configuration with optional service and path escaping settings
*/
interface S3RequestPresignerOptions {
/** AWS credentials provider or static credentials */
credentials: AwsCredentialIdentity | Provider<AwsCredentialIdentity>;
/** AWS region or region provider */
region: string | Provider<string>;
/** SHA-256 hash implementation */
sha256: ChecksumConstructor | HashConstructor;
/** Service name for signing (optional, defaults to "s3") */
service?: string;
/** Signing service name override (optional) */
signingName?: string;
/** Whether to URI escape the path (optional, defaults to false for S3) */
uriEscapePath?: boolean;
/** Whether to apply checksum (optional, defaults to false) */
applyChecksum?: boolean;
/** Runtime information (optional) */
runtime?: string;
}
/**
* Options for presigning requests
*/
interface RequestPresigningArguments {
/** Expiration time in seconds (default: 900) */
expiresIn?: number;
/** Date to use for signing (optional, defaults to current time) */
signingDate?: Date;
/** AWS region for signing (optional, uses client region) */
signingRegion?: string;
/** AWS service name for signing (optional, defaults to "s3") */
signingService?: string;
/** Headers that should not be signed */
unsignableHeaders?: Set<string>;
/** x-amz-* headers that must be present in the request */
unhoistableHeaders?: Set<string>;
/** Non-x-amz-* headers that should be signed and enforced */
signableHeaders?: Set<string>;
/** x-amz-* headers that can be hoisted to query parameters */
hoistableHeaders?: Set<string>;
}
/**
* AWS credential identity
*/
interface AwsCredentialIdentity {
/** AWS access key ID */
accessKeyId: string;
/** AWS secret access key */
secretAccessKey: string;
/** Session token for temporary credentials (optional) */
sessionToken?: string;
}
/**
* HTTP request interface
*/
interface IHttpRequest {
/** HTTP method */
method: string;
/** Protocol (https:) */
protocol: string;
/** Hostname */
hostname: string;
/** Request path */
path: string;
/** Request headers */
headers: Record<string, string>;
/** Query parameters (optional) */
query?: Record<string, string>;
/** Request body (optional) */
body?: any;
/** Port number (optional) */
port?: number;
}The package provides several constants used in the signing process.
/** Payload signature for unsigned payloads */
const UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
/** Header name for SHA256 content hash */
const SHA256_HEADER = "X-Amz-Content-Sha256";
/** Query parameter names for signature components */
const ALGORITHM_QUERY_PARAM = "X-Amz-Algorithm";
const CREDENTIAL_QUERY_PARAM = "X-Amz-Credential";
const AMZ_DATE_QUERY_PARAM = "X-Amz-Date";
const SIGNED_HEADERS_QUERY_PARAM = "X-Amz-SignedHeaders";
const EXPIRES_QUERY_PARAM = "X-Amz-Expires";
const HOST_HEADER = "host";
const ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256";The presigner may throw errors in the following scenarios:
Common error handling pattern:
try {
const url = await getSignedUrl(client, command, { expiresIn: 3600 });
return url;
} catch (error) {
if (error.message.includes("Request to be presigned is not an valid HTTP request")) {
// Handle invalid request format
} else if (error.name === "CredentialsProviderError") {
// Handle missing or invalid credentials
} else {
// Handle other signing errors
}
throw error;
}