#Using AbortController with Astro Actions.

37 messages Β· Page 1 of 1 (latest)

summer ether
#

Hey folks, I have a question. Does anyone know how to use Astro Actions with an AbortController?

I am aware of the fact that you can use getActionPath() like this:

const formData = new FormData();
formData.append('image', entry.file);

const req = await fetch(getActionPath(actions.products.uploadImage),
    {
        method: 'POST',
        signal: abortControllerRef.current?.signal,
        body: formData,
    });

const res = await req.json();

But there are 2 problems here.

  1. You lose type-safety. Perhaps this can be fixed with a type assertion, although I consider this a bit of a bad practice.
const res = await req.json() as Awaited<ReturnType<typeof actions.products.uploadImage>>;
  1. The above is actually incorrect, because the data returned is not in a regular format, and I probably need to use the devalue library to process the result.

My question is, is there an established or accepted pattern for this use case.

flint gust
#

Hello @summer ether

Still having trouble with this?

I have personally only used AbortController within an action not as part of the action call, however I can call in the support patrol as backup if you still need assistance houston_fingerguns

summer ether
#

it's just too complicated, i have to install 3rd party libs like devalue, lose all type safety and whatnot

#

(at least to my knowledge)

#

which then kind of defeats the purpose of using actions, they shine with their nice integration and type safety

#

using an abortcontroller within the action itself, i don't think there is an issue with that, i needed the abortcontroller on the frontend

flint gust
#

Absolutely, that's why I was going to call in backup if you still want to try for this solution!

Just let me know πŸ™‚

summer ether
#

please forgive my ignorance, but what do you mean by calling a backup?

flint gust
#

As a member of the support patrol I have the power to ping the other support patrol members for issues I need help with or that are unsovled πŸ™‚

summer ether
#

ohh

flint gust
#

Even though I don't know the solution, maybe someone does

Or can confirm what you've already discovered perhaps

summer ether
#

well, thank you for this kind offer but im not really sure there is anything to do be done here

#

i could use help with something similar i am trying to solve at the moment

#

but idk

flint gust
#

Well if you do decide to feel free to ping me directly, and if you have another issue you are more than welcome to open additional support threads! (you can ping me as well, I don't mind. Always good learning opportunities)

summer ether
#

also, just i've never seen this level of support in an open source project. and the other week i opened an issue on github and it was fixed like 3-4 hrs later, you guys are doing amazing job

summer ether
#

ok, i will keep it mega short, i promise

summer ether
#

I'm running nginx as reverse-proxy behind my astro app. I have a location block that intercepts an action endpoint, and checks client_max_body_size so we can prevent large file uploads. I also use it for rate limiting (not shown in this example).

location = /_actions/products.uploadImage {
    proxy_pass http://localhost:4321;
    proxy_http_version 1.1;

    client_max_body_size 25M;
}

error_page 413 = @json_413;

location @json_413 {
    default_type application/json;
    return 413 '{"error":"Request Entity Too Large"}';
}

If a user hits this location with a very large file, nginx won't even proxy the response back to the Astro server, instead it will send the response directly to the client (browser), which is all expected. I want to be able to read the status code of the nginx response (413 in this example), but the astro action caller, (which under the good uses fetch) does report a different error code.

const { data, error } = await actions.products.uploadImage(formData);

// here if we encounter an error 413 from nginx, it will instead be of this type:
console.log(JSON.stringify(error, null, 4));
// {
//    "type": "AstroActionError",
//    "code": "INTERNAL_SERVER_ERROR",
//    "status": 500
//}

// instead, if we do a raw fetch call to the same endpoint, it would return correct status code:
var req = await fetch('https://localhost/_actions/products.uploadImage/',{
    method: 'post',
    body: formData
});
console.log(req);
// {
//  "status": 413
// }

So anyway, I was just wondering the actions method returns a different error code and if there is a way to fix that. I am of course aware I can use getActionPath and do a raw fetch call with it, but that brings us back to the point I made earlier about type-safety and having to use external libs such as devalue.

#

sorry if this is too long, if you don't have time i will figure something out no issues

flint gust
#

I've also had issues with action errors being generic like that

I'm not 100% sure but I think you would have to run a check for the 413 error within the action and then return a new ActionError with the same error code

https://docs.astro.build/en/reference/modules/astro-actions/#actionerror

Again not 100% sure, what you are doing is a bit more than the simple actions I've made πŸ˜…

summer ether
#

right, but where/how do i do this check exactly?

#

wait let me see this article

#

hmm, but I think ActionError is used when you want to throw an error on the server and send that to the client

#

so of course this would work in theory, but here the request isn't even touching our astro server, it goes from client -> nginx -> client (error 413)

#

The ActionError() constructor is used to create errors thrown by an action handler yeah, this is server-side code only. i mean i may be able to use it on the client too, but it wont help me figure out what error nginx returned πŸ€”

#

i think i gotta do a raw fetch here, no other way

flint gust
#

Seems like it, or perhaps just using a normal endpoint instead of an action

summer ether
#

hey, one last question, or more like an advice. would it be a good idea to propose about AbortController support and maybe exposing raw fetch response in the Planning Astro 6.0 thread on github?

#

I thought about it already but I am being careful because idk if those are even good ideas

flint gust
summer ether
#

great idea, thank you.

#

i think i'd be more at liberty there and have more room to explain also

#

hey thanks a lot for your time, i appreciate the help. i will mark this thread as solved