[wip] presigned url version of handleUpload#1059
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
501d37d to
4fed205
Compare
dfec20e to
3e9a3e0
Compare
| options.ifMatch !== undefined | ||
| ) { | ||
| throw new BlobError( | ||
| "client/`upload` doesn't allow `addRandomSuffix`, `cacheControlMaxAge`, `allowOverwrite` or `ifMatch`. Configure these options at the server side when generating client tokens.", |
There was a problem hiding this comment.
i need to update messaging here
| signature: string; | ||
| body: string; | ||
| }): Promise<boolean> { | ||
| console.warn('verifyCallbackSignaturePresigned is not yet implemented'); |
| const resolvedWebhookPublicKey = | ||
| webhookPublicKey ?? process.env.BLOB_WEBHOOK_PUBLIC_KEY; | ||
| if (!resolvedWebhookPublicKey) { | ||
| throw new BlobError('Missing webhook public key'); |
There was a problem hiding this comment.
should we error here? or only when doing webhook callback, if onUploadCompleted is provided
| const BLOB_PRESIGN_QUERY_DELEGATION = 'vercel-blob-delegation' as const; | ||
|
|
||
| function normalizeDelegationStoreId(storeId: string): string { | ||
| const lowercase = storeId.toLowerCase(); |
There was a problem hiding this comment.
im not actually sure if we should be lowercasing store ids. Idk if they are case sensitive
ef94e63 to
1750415
Compare
|
merged into |
* [wip] presigned url version of handleUpload * up * up * up * add presigned urls for mpu * update options shape * webhook signature * update example * up * up * up * change to operation
* [wip] presigned url version of handleUpload * up * up * up * add presigned urls for mpu * update options shape * webhook signature * update example * up * up * up * change to operation
* presigned urls * up * normalize * fix * update to new signing string * [wip] presigned url version of handleUpload (#1059) * [wip] presigned url version of handleUpload * up * up * up * add presigned urls for mpu * update options shape * webhook signature * update example * up * up * up * change to operation * up * up * verify webhook signature * up * callbackUrl * non-null * presigned url opts * new delegation token + url opts * dont lowercase store id * validUntil instead of ttlSeconds * up * up * Add 'delete' to DelegationOperation for presigned DELETE URLs (#1061) Mirrors the API-side change that adds `delete` to the issue_signed_token allowed operations. `presignUrl` now signs canonical `operation=delete\npathname=...` against the public blob object URL (same host shape as `get`/`head`, just used with HTTP DELETE). Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * change upload to put * delete * up * presigned url payload * update app * fix * docs * refactor presign url * up * up * up * add head * up * add params to url * add keys first * token payload * add buildPresignedGetUrl * up * presignUrl returns url, not accepted in sdk methods * up * up * feat(blob): presigned HEAD & DELETE URLs (#1064) * feat(blob): presigned DELETE URLs Wires the `'delete'` DelegationOperation (added in #1061, since rebased out of elliot/presigned-urls) through `presignUrl`. A token issued with `operations: ['delete']` can now mint a presigned `DELETE /?pathname=…` against the control-plane API. - `PresignDeleteUrlOptions` accepts `pathname`, optional `validUntil`, optional `ifMatch`. Upload-only fields are rejected at the type level. - `presign()` gates on the delegation scope including `'delete'`. - `buildPresignedDeleteUrl()` mirrors the PUT URL shape; the HTTP method is the discriminator (canonical signing string carries `operation=delete`). - `buildPresignCanonicalQueryEntries()` for `delete` emits only `validUntil` (when below the delegation ceiling) and `ifMatch`. - E2E test route + delete button on the presigned-upload demo page. Based on `elliot/presigned-urls`, not `main`. * feat(blob): presigned HEAD URLs (#1065) `HEAD` mirrors `GET` against the blob object host (`<storeId>.<access>.blob.vercel-storage.com/<pathname>`); the URL shape is identical and the HTTP method is the discriminator. `operation=head` goes into the canonical signing string so a GET-signed URL cannot be replayed as a HEAD (and vice versa). - `'head'` added to `DelegationOperation`. - `PresignHeadUrlOptions` — same shape as `PresignGetUrlOptions` (`pathname`, optional `validUntil`). - `presign()` gates on the delegation scope including `'head'`. - `presignUrl()` reuses `buildPresignedGetUrl()` for `operation: 'head'`. - `buildPresignCanonicalQueryEntries()` for `head` emits only `validUntil` (when below the delegation ceiling) — same as `get`. - E2E test route + HEAD button on the presigned-upload demo page. Stacked on `falcoagustin/presigned-delete-impl` (#1064). * environment error * up * cleanup --------- Co-authored-by: Agustin Falco <agusfalco_11@hotmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add Vercel OIDC auth * up * header * up * prioritize token * normalize storeId in OIDC auth resolution BLOB_STORE_ID and the storeId option are accepted in either store_<id> or <id> form (Vercel env pull writes the prefixed form), and may be mixed-case. resolveBlobAuth was passing those through verbatim, so the storeId in API headers and CDN host subdomains could be malformed — e.g. blob.get against a private store with `store_WdsHBk1w9fDO4vPW` built `https://store_WdsHBk1w9fDO4vPW.private.blob.vercel-storage.com/...` and 404'd. The RW path was unaffected because parseStoreIdFromReadWriteToken yields a bare lowercase id from the token's structure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * preserve case when normalizing storeId The first pass also lowercased — that breaks API requests, since the Vercel Blob API is case-sensitive on the storeId (header and bearer parsing). The CDN host accepts either case, so prefix-strip alone is sufficient and works for both consumers. Verified end-to-end against a private store: blob get and blob list both succeed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * add oidcToken option * minor version * Vercel Presigned URLs (#1057) * presigned urls * up * normalize * fix * update to new signing string * [wip] presigned url version of handleUpload (#1059) * [wip] presigned url version of handleUpload * up * up * up * add presigned urls for mpu * update options shape * webhook signature * update example * up * up * up * change to operation * up * up * verify webhook signature * up * callbackUrl * non-null * presigned url opts * new delegation token + url opts * dont lowercase store id * validUntil instead of ttlSeconds * up * up * Add 'delete' to DelegationOperation for presigned DELETE URLs (#1061) Mirrors the API-side change that adds `delete` to the issue_signed_token allowed operations. `presignUrl` now signs canonical `operation=delete\npathname=...` against the public blob object URL (same host shape as `get`/`head`, just used with HTTP DELETE). Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * change upload to put * delete * up * presigned url payload * update app * fix * docs * refactor presign url * up * up * up * add head * up * add params to url * add keys first * token payload * add buildPresignedGetUrl * up * presignUrl returns url, not accepted in sdk methods * up * up * feat(blob): presigned HEAD & DELETE URLs (#1064) * feat(blob): presigned DELETE URLs Wires the `'delete'` DelegationOperation (added in #1061, since rebased out of elliot/presigned-urls) through `presignUrl`. A token issued with `operations: ['delete']` can now mint a presigned `DELETE /?pathname=…` against the control-plane API. - `PresignDeleteUrlOptions` accepts `pathname`, optional `validUntil`, optional `ifMatch`. Upload-only fields are rejected at the type level. - `presign()` gates on the delegation scope including `'delete'`. - `buildPresignedDeleteUrl()` mirrors the PUT URL shape; the HTTP method is the discriminator (canonical signing string carries `operation=delete`). - `buildPresignCanonicalQueryEntries()` for `delete` emits only `validUntil` (when below the delegation ceiling) and `ifMatch`. - E2E test route + delete button on the presigned-upload demo page. Based on `elliot/presigned-urls`, not `main`. * feat(blob): presigned HEAD URLs (#1065) `HEAD` mirrors `GET` against the blob object host (`<storeId>.<access>.blob.vercel-storage.com/<pathname>`); the URL shape is identical and the HTTP method is the discriminator. `operation=head` goes into the canonical signing string so a GET-signed URL cannot be replayed as a HEAD (and vice versa). - `'head'` added to `DelegationOperation`. - `PresignHeadUrlOptions` — same shape as `PresignGetUrlOptions` (`pathname`, optional `validUntil`). - `presign()` gates on the delegation scope including `'head'`. - `presignUrl()` reuses `buildPresignedGetUrl()` for `operation: 'head'`. - `buildPresignCanonicalQueryEntries()` for `head` emits only `validUntil` (when below the delegation ceiling) — same as `get`. - E2E test route + HEAD button on the presigned-upload demo page. Stacked on `falcoagustin/presigned-delete-impl` (#1064). * environment error * up * cleanup --------- Co-authored-by: Agustin Falco <agusfalco_11@hotmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * up * rm dead code * throw on manual token * up * up --------- Co-authored-by: Agustin Falco <agusfalco_11@hotmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
No description provided.