Skip to content

feat(storage): add support for upload presigned url - #4146

Merged
harsh62 merged 8 commits into
mainfrom
storage-get-url-change
Apr 10, 2026
Merged

feat(storage): add support for upload presigned url#4146
harsh62 merged 8 commits into
mainfrom
storage-get-url-change

Conversation

@harsh62

@harsh62 harsh62 commented Feb 19, 2026

Copy link
Copy Markdown
Contributor

Description

Extends the existing getUrl Storage API to support pre-signed URL generation for PUT (upload) operations, enabling developers to use third-party tools and HTTP clients to upload files to S3 via Amplify.

What changed

  • New StorageAccessMethod enum at the category level (Amplify/Categories/Storage/StorageAccessMethod.swift) with .get and .put cases — follows the cross-platform naming convention from the approved mobile API review doc (Flutter, Android, Swift all use StorageAccessMethod)
  • Updated AWSStorageGetURLOptions to accept a method: StorageAccessMethod parameter (defaults to .get)
  • Updated AWSS3StorageGetURLTask to select AWSS3SigningOperation.putObject or .getObject based on the method parameter

Behavior

Option Behavior
method: .get (default) Existing behavior — generates a presigned download URL
method: .put Generates a presigned URL for uploading via HTTP PUT
validateObjectExistence Skipped when method is .put (object may not exist yet)
useAccelerateEndpoint Works with both .get and .put
expiresIn Works with both .get and .put

Usage

// Generate a presigned upload URL
let putURL = try await Amplify.Storage.getURL(
    path: .fromString("uploads/photo.jpg"),
    options: .init(
        pluginOptions: AWSStorageGetURLOptions(method: .put)
    )
)

// Use with any HTTP client
var request = URLRequest(url: putURL)
request.httpMethod = "PUT"
request.httpBody = fileData
let (_, response) = try await URLSession.shared.data(for: request)

Breaking Changes

None. The method parameter is optional and defaults to .get. Existing code continues to work unchanged.

Test Coverage

  • Unit tests: Options initializer tests, task signing operation mapping, validation errors
  • Property-based tests (100 iterations each): method-to-signing mapping, expiration forwarding, object existence validation conditional on method, accelerate forwarding
  • Integration tests: Full round-trip PUT upload + GET download verification, existence validation skip for PUT, backward compatibility

General Checklist

  • Added new tests to cover change, if needed
  • Build succeeds with all target using Swift Package Manager
  • All unit tests pass
  • All integration tests pass
  • Security oriented best practices and standards are followed (e.g. using input sanitization, principle of least privilege, etc)
  • Documentation update for the change if required
  • PR title conforms to conventional commit style
  • New or updated tests include Given When Then inline code documentation and are named accordingly testThing_condition_expectation()
  • If breaking change, documentation/changelog update with migration instructions

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov

codecov Bot commented Feb 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.79%. Comparing base (7c6a32a) to head (e5c8455).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4146      +/-   ##
==========================================
+ Coverage   66.53%   66.79%   +0.25%     
==========================================
  Files        1150     1150              
  Lines       43607    43617      +10     
==========================================
+ Hits        29013    29133     +120     
+ Misses      14594    14484     -110     
Flag Coverage Δ
API_plugin_unit_test 68.42% <ø> (+0.20%) ⬆️
AWSPluginsCore 68.07% <ø> (ø)
Amplify 46.81% <ø> (ø)
Amplify_Foundation_Bridge_unit_test 62.28% <ø> (ø)
Amplify_Foundation_unit_test 67.64% <ø> (ø)
Analytics_plugin_unit_test 83.43% <ø> (ø)
Auth_plugin_unit_test 72.47% <ø> (+0.17%) ⬆️
DataStore_plugin_unit_test 82.77% <ø> (+0.90%) ⬆️
Firehose_plugin_unit_test 53.15% <ø> (ø)
Geo_plugin_unit_test 73.39% <ø> (ø)
Kinesis_plugin_unit_test 52.17% <ø> (ø)
Logging_plugin_unit_test 64.86% <ø> (ø)
Predictions_plugin_unit_test 33.89% <ø> (ø)
PushNotifications_plugin_unit_test 85.66% <ø> (ø)
RecordCache_unit_test 76.40% <ø> (ø)
Storage_plugin_unit_test 78.10% <100.00%> (+0.42%) ⬆️
unit_tests 66.79% <100.00%> (+0.25%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…iew doc

Replace plugin-level HTTPMethod enum with category-level StorageAccessMethod
enum per the approved mobile API review doc. Remove contentType support (not
in approved scope, tracked as future work). Delete .kiro spec files.
@harsh62
harsh62 marked this pull request as ready for review April 9, 2026 14:45
@harsh62
harsh62 requested a review from a team as a code owner April 9, 2026 14:45
@harsh62
harsh62 force-pushed the storage-get-url-change branch from 05c6af4 to b20682e Compare April 9, 2026 15:49
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
@harsh62
harsh62 temporarily deployed to IntegrationTest April 9, 2026 19:40 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants