summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/sixty-fishes-flow.md6
-rw-r--r--packages/astro/e2e/actions-blog.test.js2
-rw-r--r--packages/astro/src/actions/consts.ts2
-rw-r--r--packages/astro/test/actions.test.js12
-rw-r--r--packages/integrations/react/server.js6
-rw-r--r--packages/integrations/react/src/actions.ts6
6 files changed, 19 insertions, 15 deletions
diff --git a/.changeset/sixty-fishes-flow.md b/.changeset/sixty-fishes-flow.md
new file mode 100644
index 000000000..eac560adc
--- /dev/null
+++ b/.changeset/sixty-fishes-flow.md
@@ -0,0 +1,6 @@
+---
+'@astrojs/react': minor
+'astro': minor
+---
+
+Changes the generated URL query param from `_astroAction` to `_action` when submitting a form using Actions. This avoids leaking the framework name into the URL bar, which may be considered a security issue.
diff --git a/packages/astro/e2e/actions-blog.test.js b/packages/astro/e2e/actions-blog.test.js
index 7d362334e..84981f078 100644
--- a/packages/astro/e2e/actions-blog.test.js
+++ b/packages/astro/e2e/actions-blog.test.js
@@ -162,7 +162,7 @@ test.describe('Astro Actions - Blog', () => {
await page.goto(astro.resolveUrl('/sum'));
const submitButton = page.getByTestId('submit');
await submitButton.click();
- await expect(page).toHaveURL(astro.resolveUrl('/sum?_astroAction=sum'));
+ await expect(page).toHaveURL(astro.resolveUrl('/sum?_action=sum'));
const p = page.locator('p').nth(0);
await expect(p).toContainText('Form result: {"data":3}');
});
diff --git a/packages/astro/src/actions/consts.ts b/packages/astro/src/actions/consts.ts
index 35137df59..88fafb8a3 100644
--- a/packages/astro/src/actions/consts.ts
+++ b/packages/astro/src/actions/consts.ts
@@ -6,7 +6,7 @@ export const RESOLVED_VIRTUAL_INTERNAL_MODULE_ID = '\0astro:internal-actions';
export const NOOP_ACTIONS = '\0noop-actions';
export const ACTION_QUERY_PARAMS = {
- actionName: '_astroAction',
+ actionName: '_action',
actionPayload: '_astroActionPayload',
};
diff --git a/packages/astro/test/actions.test.js b/packages/astro/test/actions.test.js
index 257bf0284..d8da4e72e 100644
--- a/packages/astro/test/actions.test.js
+++ b/packages/astro/test/actions.test.js
@@ -220,7 +220,7 @@ describe('Astro Actions', () => {
});
it('Response middleware fallback - POST', async () => {
- const req = new Request('http://example.com/user?_astroAction=getUser', {
+ const req = new Request('http://example.com/user?_action=getUser', {
method: 'POST',
body: new FormData(),
headers: {
@@ -237,7 +237,7 @@ describe('Astro Actions', () => {
it('Response middleware fallback - cookie forwarding', async () => {
const req = new Request(
- 'http://example.com/user?_astroAction=getUser&actionCookieForwarding=true',
+ 'http://example.com/user?_action=getUser&actionCookieForwarding=true',
{
method: 'POST',
body: new FormData(),
@@ -255,7 +255,7 @@ describe('Astro Actions', () => {
});
it('Respects custom errors - POST', async () => {
- const req = new Request('http://example.com/user-or-throw?_astroAction=getUserOrThrow', {
+ const req = new Request('http://example.com/user-or-throw?_action=getUserOrThrow', {
method: 'POST',
body: new FormData(),
headers: {
@@ -273,7 +273,7 @@ describe('Astro Actions', () => {
it('Respects custom errors - cookie forwarding', async () => {
const req = new Request(
- 'http://example.com/user-or-throw?_astroAction=getUserOrThrow&actionCookieForwarding=true',
+ 'http://example.com/user-or-throw?_action=getUserOrThrow&actionCookieForwarding=true',
{
method: 'POST',
body: new FormData(),
@@ -320,8 +320,8 @@ describe('Astro Actions', () => {
assert.equal('safe' in data, true);
});
- it('Ignores `_astroAction` name for GET requests', async () => {
- const req = new Request('http://example.com/user-or-throw?_astroAction=getUserOrThrow', {
+ it('Ignores action name for GET requests', async () => {
+ const req = new Request('http://example.com/user-or-throw?_action=getUserOrThrow', {
method: 'GET',
});
const res = await app.render(req);
diff --git a/packages/integrations/react/server.js b/packages/integrations/react/server.js
index 69b0a8e12..9c3c309cc 100644
--- a/packages/integrations/react/server.js
+++ b/packages/integrations/react/server.js
@@ -126,11 +126,7 @@ async function getFormState({ result }) {
* This matches the endpoint path.
* @example "/_actions/blog.like"
*/
- const actionName =
- searchParams.get('_astroAction') ??
- /* Legacy. TODO: remove for stable */ formData
- .get('_astroAction')
- ?.toString();
+ const actionName = searchParams.get('_action');
if (!actionKey || !actionName) return undefined;
diff --git a/packages/integrations/react/src/actions.ts b/packages/integrations/react/src/actions.ts
index a5ccb2f9a..06ecd4148 100644
--- a/packages/integrations/react/src/actions.ts
+++ b/packages/integrations/react/src/actions.ts
@@ -26,7 +26,7 @@ export function experimental_withState<T>(action: FormFn<T>) {
// Called by React when form state is passed from the server.
// If the action names match, React returns this state from `useActionState()`.
callback.$$IS_SIGNATURE_EQUAL = (incomingActionName: string) => {
- const actionName = new URLSearchParams(action.toString()).get('_astroAction');
+ const actionName = new URLSearchParams(action.toString()).get('_action');
return actionName === incomingActionName;
};
@@ -46,7 +46,9 @@ export function experimental_withState<T>(action: FormFn<T>) {
*/
export async function experimental_getActionState<T>({
request,
-}: { request: Request }): Promise<T> {
+}: {
+ request: Request;
+}): Promise<T> {
const contentType = request.headers.get('Content-Type');
if (!contentType || !isFormRequest(contentType)) {
throw new AstroError(