Skip to content

Commit

Permalink
Rename Action query param to _action (#12510)
Browse files Browse the repository at this point in the history
* rename _astroAction to _action

* changeset
  • Loading branch information
bholmesdev authored Nov 25, 2024
1 parent 30c78ba commit 14feaf3
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 15 deletions.
6 changes: 6 additions & 0 deletions .changeset/sixty-fishes-flow.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion packages/astro/e2e/actions-blog.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}');
});
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/actions/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
};

Expand Down
12 changes: 6 additions & 6 deletions packages/astro/test/actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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(),
Expand All @@ -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: {
Expand All @@ -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(),
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 1 addition & 5 deletions packages/integrations/react/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
6 changes: 4 additions & 2 deletions packages/integrations/react/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand All @@ -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(
Expand Down

0 comments on commit 14feaf3

Please sign in to comment.