W
Wasp-lang12mo ago
DimAss

API CORS error

Hi, I'm trying to fetch a PUT endpoint, but it throws a CORS error in the console (testing locally). Frontend is on localhost:3000, backend is on localhost:3001 What am I doing wrong?
No description
No description
No description
18 Replies
DimAss
DimAss12mo ago
Request headers:
No description
DimAss
DimAss12mo ago
I also tried to manually set CORS headers for that endpoint, but it didn't help
No description
DimAss
DimAss12mo ago
Interesting, this only happens when I'm logged in using Google Auth... No CORS errors when there is no auth session, tried with Chrome and Firefox
miho
miho12mo ago
If you are looking to update a product, a more natural mechanism in Wasp is using actions. Wasp has an RPC setup between backend and client, so you don't have to mess around too much with setting up APIs by hand. The RPC has queries and actions. With queries you get your products for example, and with actions you make changes. Here's the part of the docs that discusses that: https://wasp-lang.dev/docs/language/features#queries-and-actions-aka-operations For example, you would declare in your Wasp file:
action updateProduct {
fn: import { updateProduct } from "@server/actions.js",
entities: [Product]
}
action updateProduct {
fn: import { updateProduct } from "@server/actions.js",
entities: [Product]
}
and then write the implementation in actions.ts/js
export const updateProduct = (args, context) => {
return context.entities.Product.update({ where: { id: args.id }, ...}
}
export const updateProduct = (args, context) => {
return context.entities.Product.update({ where: { id: args.id }, ...}
}
And then use it on the frontend
import updateProduct from "@wasp/actions/updateProduct"
...
import updateProduct from "@wasp/actions/updateProduct"
...
miho
miho12mo ago
APIs on the other hand were more envisioned as escape hatches for when you really need more control. For example, a webhook for Stripe payments being one of the use cases. The APIs don't come with all of the middleware setup to prevent collisons. So you need to set them up with ideally apiNamespace and a middleware function.
DimAss
DimAss12mo ago
Hi @miho I haven't found a way to use HTTP verbs with actions, all action requests are done via POST. Is there a way to change that?
miho
miho12mo ago
That's the way the current RPC functions, do you have a use case where you need the PUT verb? 🙂 Maybe something for us to change in the future 🤷‍♂️
DimAss
DimAss12mo ago
Well, for example I'm using react-admin and it expects GET/POST/PUT/DELETE to do entity manipulations @miho so no default middlewares are applied to api endpoints?
miho
miho12mo ago
Hmm that's really interesting! We will play with react-admin ourselves and see what's the best path forward. In the meantime, if you really want to make your api work, please consider doing this: https://wasp-lang.dev/docs/guides/middleware-customization#3-customize-per-path-middleware
Middleware Customization | Wasp
Wasp comes with a minimal set of useful Express middleware in every application. While this is good for most users, we realize some may wish to add, modify, or remove some of these choices both globally, or on a per-api/path basis.
miho
miho12mo ago
@miho so no default middlewares are applied to api endpoints?
They are applied to the put but not options keyword which breaks the CORS behaviour (we are looking into fixing this on the framework level) If you define /api -> apiNamespace and then define the middleware there to apply, it should work 🙂 Let me write you an example, gimme a minute
DimAss
DimAss12mo ago
I managed to fix it by copying the default middleware and adding it to apiNamespace, thank you! However, this is an extremely unpredictable behaviour, so it might be a good idea to mention the lack of middlewares for API endpoints in docs 🙂
No description
No description
miho
miho12mo ago
Nice! You could have just returned the input middleware you received 😄
import { MiddlewareConfigFn } from "@wasp/middleware"
export const apiMiddleware: MiddlewareConfigFn = (config) => {
return config;
}
import { MiddlewareConfigFn } from "@wasp/middleware"
export const apiMiddleware: MiddlewareConfigFn = (config) => {
return config;
}
Why this works as well, the config already contains all the default middleware (one of them is CORS)
DimAss
DimAss12mo ago
Aha, got it 🙂
miho
miho12mo ago
Thank you for the patience and testing Wasp, let us know if you stumble upon any other issues. We will explore how to better support react-admin out of the box and similar needs for using Wasp as just the server 🙂
DimAss
DimAss12mo ago
Btw this doc example is kinda misleading as well, since that header setup does not really work properly
No description
DimAss
DimAss12mo ago
Sure, thank you for your help!
martinsos
martinsos12mo ago
This might be interesting: there is a piece in react-admin docs that says how to support RPC like Wasp has, by adding custom methods to your data provider, it also mentions useQuery -> so I would say it is probably very close / exactly what you need, check it out: https://marmelab.com/react-admin/Actions.html#calling-custom-methods .
martinsos
martinsos12mo ago
Thanks @DimAss for feedback so far, I create two issues to capture what was said here: https://github.com/wasp-lang/wasp/issues/1303 https://github.com/wasp-lang/wasp/issues/1304 so we will be able to work in the future on improving Wasp for these use cases!