Action API #427
Replies: 5 comments 2 replies
-
This seems interesting |
Beta Was this translation helpful? Give feedback.
-
I think this RFC + Endpoints v2 (to handle things like auth) are the missing piece of Astro SSR to adopt it before other frameworks. |
Beta Was this translation helpful? Give feedback.
-
Funny enough, coming from Remix, I was experimenting with something similar and was going to open this discussion 😊 . As of now, Astro is very good for initial load and "JavaScript sparkling" with the island architecture. However, the user's adventures do not stop after the page has finished loading. This RFC looks very promising to me in the sense that it can be done in a framework-agnostic way and covers the subsequent navigation experience of a user. Kudos for the RFC, and I would love to see something similar landing in the tool 👏🏻 👏🏻 |
Beta Was this translation helpful? Give feedback.
-
Love it! |
Beta Was this translation helpful? Give feedback.
-
This is an awesome discussion! I'm happy to share that actions have landed as a stage 2 proposal ready to enter stage 3 soon. There are some key ideas from this thread that really resonate:
I think all of these points should inform the final API. Closing to track here: #898 |
Beta Was this translation helpful? Give feedback.
-
Add a built in way to handle form submissions (actions) and implement forms with progressive enhancements
This was originally based on my implementation but it's now updated to be based on an actual library: https://github.com/pilcrowOnPaper/astro-form-actions
Why?
While Astro is a static-first framework, I truly believe it can be great framework for building dynamic websites, including those with some user interactions. Something like a forum with authentication. It's mostly rendering dynamic content with a few forms for login, making posts, and replying to posts. SSR is already implemented and it already has an API for handling requests/responses in pages, as well as support for API routes. The only major thing missing now is a way to handle forms. Frameworks like SvelteKit and Remix makes it easy to with their own
action
API, and I think Astro could implement one as well.One may forget to implement proper CSRF protection as well.
API
Handling form submissions
Pages can export an asynchronous
action
function, which will handle form submissions, specificallyPOST
requests with aContent-Type
header ofmultipart/form-data
orapplication/x-www-form-urlencoded
. Thisaction()
will run before any server side code in the page file.It only accept a single argument:
formData
. This will be theFormData
object sent with the request, which includes both string and file input. The request, response, url, etc can be accessed from the Astro global object.action()
must return one of 3 responses:Resolved
(success),Rejected
(error),Redirected
(redirect). These are created usingresolve()
,reject()
, andredirect()
respectively.resolve()
takes a POJO,reject()
takes a status code and POJO, andredirect()
takes a status code and location. All three functions can be imported fromastro/actions
(some module).After handling the form submission, if the request was sent by the browser (native way), it will immediately return a redirect response on redirect or simply re-render the page on success or error. If the request was sent using client-side JavaScript (
fetch()
), it will return a JSON response immediately regardless of the response type. The only time it will modify the status code ofAstro.response
is if it's an error response for a native form submission.The result of action (
resolve()
) can be retrieved usingAstro.useActionResult<Action>()
.This will take the type of
action
as the generic, and return the following type:Type
Body
will be the argument forresolved()
, andErrorData
will be the 2nd argument forrejected()
. See library for implementation.Submitting forms
Forms can be submitted as is (handled by the browser), or using the
submitForm()
function imported fromastro/forms
. In either case, a form element is used.submitForm()
is a generic function that can be used with any JS framework. It takes 2 arguments: the htmlform
element, and a optional redirect handler. Since the redirect will be handled if JavaScript, it may be useful to use client side navigation rather than server side navigation. The default behavior is to usewindow.location.href
to redirect.Return type is as follow (
ActionResult
withoutinputValues
):Constraints
POST
forms. I don't think an API forGET
is necessary though.Example
Form component with progressive enhancements
This example uses Solid.
This will update the error message when it returns one, and will work regardless of the availability of client side JavaScript.
Details
Encoding type
The request should be cloned before doing anything with it.
Since the
formData()
method of nativeRequest
object only supportsapplication/x-www-form-urlencoded
, a parse must be used (eg.parse-multipart-data
used by SolidStart). This is the only external dependency necessary.See here for transforming form request body to
FormData
.Redirect responses
When using
fetch()
and a redirect response with a location header is returned, it will try to call a cross-site request to the redirect location. As such, responses for requests made withfetch()
must not include the location header and the redirect location should be included in the response body.The response body could look something like this:
CSRF protection
By default, actions should only accept requests coming from the same origin it's hosted. This is a MUST if this feature is to be implemented. This can be achieved using the
Origin
header, which all modern browsers support. It should be possible to disable feature, either in a config file or by passing on an option toaction()
, for those who want to support older browsers.Type safety
See https://github.com/pilcrowOnPaper/astro-form-actions for how the result can be properly typed.
Types for the error should be declared in the form component, and TS will properly check the types when the
error
from the server is passed to it as props:https://github.com/pilcrowOnPaper/astro-form-actions/wiki/3.-Working-with-types
Beta Was this translation helpful? Give feedback.
All reactions