supabase / postgrest-js

Isomorphic JavaScript client for PostgREST.
https://supabase.com
MIT License
1.03k stars 133 forks source link

No response body for successful REST API calls (insert, update). Success messages are returned as errors and hidden by most clients. #511

Closed skwigs closed 9 months ago

skwigs commented 9 months ago

Bug report

Describe the bug

Success messages are not returned in the body of Rest API responses (e.g., insert, update). The 201 success HTTP response is captured, but the body is completely empty even when looking at it in raw.

Postman Response

The problem is the success message is being returned in the error attribute of the response. Since "returned_an_error" is false, you never see the success message.

Success Message in Errors

Note: The object in the "error" attribute (above) is the same response the JS docs v2.0 say should be returned when the call is successful (below).

JS Success Object

Workaround (and it's issues)

The workaround appears to be to "Create a record and return it". In the discussion threads, much has been said about appending .select() to your JS function as shown here. In the API, you can set the Prefer header to return=representation.

Return Representation

However, the response is again not the same as expected per the JS 2.0 docs. Only the data array is returned...

Create and return object

...and the status text continues to be in an error attribute outside the body and headers.

Representation Response

Reading the discussion threads some people have said responses worked properly in v1 and then changed in v2. There's an assumption this was intentional, but it seems more like a bug given:

  1. The response body is completely empty which is not typical. You'd expect to at least get an empty object.
  2. Success messages are generated but are not being put in the right location.
  3. The behavior doesn't match the v2 docs which say inserts and updates should return success messages.

Also, it's interesting that the Rest API is still v1, and so you'd expect it behave as it did before the upgrade. So again, this shouldn't be a case of v1 versus v2 functionality. It seems more like the success messages just aren't getting routed to the correct place in the response now.

To Reproduce

This issue was particularly difficult to track down because of how Postman and other tools like it parse API responses. I happened to be integrating Supabase with bubble.io, and their response handling allows you to see error data even when an error is not thrown.

Steps to reproduce:

  1. In Supabase, create a "todos" table with a column for "title" and disable Row Level Security
  2. Sign up for a free bubble.io account
  3. In your bubble dashboard: click Create an App (button) > give it a name > Get Started (button) > "Start with basic features" link > Skip application assistant (button)
  4. Install the Bubble API Connector by clicking "Plugins" in the left side menu > + Add plugins (button) > search for API Connector by Bubble (should be top result) > click Install (button) > Done (button).
  5. Create your Supabase call by clicking Add another API (button) > "Import another call from cURL (link)

Import from cURL

  1. Prepare the call by copying the Bash script with 1) your Supabase subdomain, and 2) your SUPABASE_CLIENT_ANON_KEY.
curl -X POST 'https://xxxxxxxxxxxxxxxxxxxx.supabase.co/rest/v1/todos' \
-H "apikey: SUPABASE_CLIENT_ANON_KEY" \
-H "Authorization: Bearer SUPABASE_CLIENT_ANON_KEY" \
-H "Content-Type: application/json" \
-H "Prefer: return=minimal" \
-d '{ "title": "buy groceries"}'
  1. Paste the bash script into the text area of the cURL popup and click Import (button).
  2. IMPORTANT: Check the boxes for "Include errors in response and allow workflow actions to continue" and "Capture response headers". The the call will fail if you don't.

Congrats. You're call settings should now look something like this.

Bubble Call Setup

  1. Run it by clicking the Initialize Call (button)
  2. At the bottom of the list of values, click "Show raw data" link to get the see the error message

Show raw data

  1. Validate the error object as described above, and check Supabase to verify the todo was created.
  2. Update the Prefer header to "return=representation" and repeat steps 9-11 to see only the data array returned in the response and not the whole object as expected in the docs.

Additional context

Since bubble requires you to initialize your APIs with a successful call, this issue kept me from integrating bubble and Supabase for along time. Checking the boxes to show errors seems to get around this constraint, but it took a long time figure out what was going on with no response object coming back form Supabase via Postman either. I'm not the only one who has experience this though as several others have run into the empty response issue as well and I'm sure the mods are tired of responding to it.

Finally, the fix to this bug could result in client impact as it may be a breaking change. For example, if the Rest API is updated to match the docs, then apps using the workaround of getting a representation object will need to be updated to access the Data property first before getting to the array with their data in it. Might be worth it to make sure there's good communication if/when a fix for this is released.

GaryAustin1 commented 9 months ago

There is already an issue open on this. https://github.com/supabase/postgrest-js/issues/405

skwigs commented 9 months ago

@GaryAustin1 Please note this issue provides more detail for troubleshooting than https://github.com/supabase/postgrest-js/issues/405 It details how the root cause of the behavior is the underlying REST API call itself and not just the JS library. It also shows the recommended workaround of returning the inserted/updated object is also impacted by the same error.

GaryAustin1 commented 9 months ago

I moved this over to Postgrest-js issues so it stays close to the other.

skwigs commented 9 months ago

Sounds good. I just wanted to make sure there was awareness as I didn't say which API in my title before. Just fixed that. Thanks!