0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00
astro/.changeset/tall-waves-impress.md

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

63 lines
2.7 KiB
Markdown
Raw Normal View History

Actions middleware (#12373) * add manual middleware config option with getMiddlewareContext() * refactor requestInfo to action object * set action error response status from render context * update automatic middleware to plain POST handler * fix missing Locals type * test: add separate POST and cookie forwarding tests * remove actions.middleware flag * add docs on actionResultAlreadySet * test: use Astro.rewrite instead of middleware next(). TODO: fix next() * fix type errors from rebase * test: remove middleware handler * test: use cookie forwarding for 'lots of fields' * refactor: _isPrerendered -> ctx.isPrerendered * expose getOriginPathname as middleware utility * add support for handling RPC action results from middleware * test: RPC security middleware * refactor POST route handler to use getMiddlewareContext() * remove unused actionRedirect flag * changeset * test: add expectedd rewrite failure for Ema to debug * fix e2e test * nit: form -> from Co-authored-by: Emanuele Stoppa <my.burning@gmail.com> * rename getMiddlewareContext -> getActionContext * rename form-action -> form * move /_actions/ route pattern to const * move type defs to user-accessible ActionMiddlewareContext type * export action middleware context type * strip omitted fields for Action API Context * add satisfies to type for good measure * move getOriginPathname to shared ctx.originPathname * remove `next()` rewrite because it isn't supported * fix empty forms raising a 415 * fix missing async on cookie example * nit: ctx -> context * fix json parse error when content length is 0 * refactor body parsing to function * edit: migration -> updating your HTML form actions Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * update changeset to match docs v5 guide * add absolute urls to changeset links --------- Co-authored-by: Emanuele Stoppa <my.burning@gmail.com> Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
2024-11-08 17:03:57 -05:00
---
'astro': minor
---
Changes the default behavior for Astro Action form requests to a standard POST submission.
In Astro 4.x, actions called from an HTML form would trigger a redirect with the result forwarded using cookies. This caused issues for large form errors and return values that exceeded the 4 KB limit of cookie-based storage.
Astro 5.0 now renders the result of an action as a POST result without any forwarding. This will introduce a "confirm form resubmission?" dialog when a user attempts to refresh the page, though it no longer imposes a 4 KB limit on action return value.
## Customize form submission behavior
If you prefer to address the "confirm form resubmission?" dialog on refresh, or to preserve action results across sessions, you can now [customize action result handling from middleware](https://5-0-0-beta.docs.astro.build/en/guides/actions/#advanced-persist-action-results-with-a-session).
We recommend using a session storage provider [as described in our Netlify Blob example](https://5-0-0-beta.docs.astro.build/en/guides/actions/#advanced-persist-action-results-with-a-session). However, if you prefer the cookie forwarding behavior from 4.X and accept the 4 KB size limit, you can implement the pattern as shown in this sample snippet:
```ts
// src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => {
// Skip requests for prerendered pages
if (context.isPrerendered) return next();
const { action, setActionResult, serializeActionResult } = getActionContext(context);
// If an action result was forwarded as a cookie, set the result
// to be accessible from `Astro.getActionResult()`
const payload = context.cookies.get('ACTION_PAYLOAD');
if (payload) {
const { actionName, actionResult } = payload.json();
setActionResult(actionName, actionResult);
context.cookies.delete('ACTION_PAYLOAD');
return next();
}
// If an action was called from an HTML form action,
// call the action handler and redirect with the result as a cookie.
if (action?.calledFrom === 'form') {
const actionResult = await action.handler();
context.cookies.set('ACTION_PAYLOAD', {
actionName: action.name,
actionResult: serializeActionResult(actionResult),
});
if (actionResult.error) {
// Redirect back to the previous page on error
const referer = context.request.headers.get('Referer');
if (!referer) {
throw new Error('Internal: Referer unexpectedly missing from Action POST request.');
}
return context.redirect(referer);
}
// Redirect to the destination page on success
return context.redirect(context.originPathname);
}
return next();
})
```