restful.js icon indicating copy to clipboard operation
restful.js copied to clipboard

Returned data from response interceptor are merged not replaced

Open pristas-peter opened this issue 10 years ago • 11 comments

Hi, we use response interceptor to decamileze data keys, however, when I call body().data() on the entity, the data contains old response keys and also the new ones. Could this behaviour be modified?

pristas-peter avatar Feb 11 '16 06:02 pristas-peter

Hi,

No it is not possible, but it is a good idea for a next version!

RobinBressan avatar Feb 11 '16 11:02 RobinBressan

Same cause, different problem: Restful can't be used with APIs which don't conform to its idea of what the responses should look like. (Which I haven't found documentation for, incidentally.)

For example, I have a API which returns a list or orgs when requesting GET /org. But it returns them as an object like so: { orgs: [ <list of orgs> ] }. I thought of adding an interceptor to transform the response to what Restful.js is expecting, but noooo, can't do that. :frowning:

passcod avatar Mar 02 '16 23:03 passcod

@passcod Can you better describe your issue? I am not sure to understand what you mean with what Restful.js is expecting.

RobinBressan avatar Mar 03 '16 09:03 RobinBressan

Ok, so when requesting a Collection, with .all, Restful expects an array to be returned by the server. That's what it says in the error it throws when my server fails to return an array. This, by the way, is the only place Restful.js says it's expecting an array for Collections, unless I've missed something in the ReadMe, which means the only way to discover that Restful.js and my server won't play well together is to actually try it out.

My server does not return an array for collections. It returns an object that describes the collection metadata, and has a key on that object which contains the actual array of objects. I cannot change the server: the server is written by another part of my team who put some thought in the responses, specced them, etc, and I can't just say "hey, can you discard all that work and make it fit like so?". Besides, I agree with them.

I suppose I could not use Collections to fetch… well, collections that just happen to be represented by an object. It would be a nasty hack and defeat the point, but it would work. I further suppose I could go the fetch-proxy route. Like this:

import restful, { fetchBackend } from 'restful.js'
const api = restful('http://api.example.com', fetchBackend(
  (url, options) => fetch(url, options).then((response) => {
    if (url points to a collection) {
      // transform response to only return the array
    }
    return response
  })
))

It's not quite elegant, though, is it?

So, my issue is that as far as I could tell, Restful.js expects API endpoints which return collections of entities actually return a JSON array, and interceptors don't actually replace the response, only merge it (and probably also run after the "check response is an array" thing, too), so I can't transform responses in such a way that my API becomes usable with this library without inelegant hacks. Sorry for unclearness.

passcod avatar Mar 03 '16 09:03 passcod

Which version of restful.js do you use? Because in the last version there is no more error triggered for this, only a warning in dev env. Otherwise maybe a .custom is better suited to your use case.

RobinBressan avatar Mar 03 '16 13:03 RobinBressan

Latest from npm. Listen, it's fine, I'm using react-refetch now. Sorry for the useless discussion. 'Good day :)

passcod avatar Mar 03 '16 13:03 passcod

Just bumped into this myself. I have similiar API response structure as @passcod

{
  ...
  data: [
    {actual: 'data'},
    {actual: 'data'}
    ...
  ]
  ...
}

Back when I used Restangular in Angular projects, I deal with this kind of data with response interceptor, and return only the data array above. And then the Restangular getAll method returns expected array of data.

In restful.js, I can't do the same, as the old 'plain object' response above merged with 'array' of data returned in my response interceptor, thus make restful.js returns response as member, not collection.

Right now, I use custom method, and treat them as object. But then I don't have all the collection goodies and each item in data array above is not a member of restful.js.

Like OP said, It'd be awesome to have options to change how data returned in response interceptor got treated. But looking at restful.js code, the interceptor is called late after data got processed into member or collection based on httpBackend response, so I don't know if it'd be possible.

panjiesw avatar May 10 '16 08:05 panjiesw

#91 may relate to this. I believe restangular lets you fix data standardization issues by using element transformers, and interceptors don't do quite the same job. Is there a reason for the interceptor to merge instead of just re-assigning at the base level keys or was it just an initial design decision without use case?

npbenjohnson avatar Aug 12 '16 19:08 npbenjohnson

This is a problem that I encountered today, restful is allowing me to define a data structure, then completely ignoring what I return and merging the result into one big amalgamation of all the return structures.

I am not sure why it was commented that this was not possible though :-/

christhomas avatar Sep 02 '16 09:09 christhomas

Same problem here. .addResponseInterceptor((res, config) => { return {data: {myData: 'val'}} }) only merged myData into original data. Can something be done about it ? It is logged in console at warning level but still it is something which behaves unexpectedly.

ps-aux avatar Dec 02 '16 12:12 ps-aux

Nowadays, Restful api responses LIST data like this:

{
   meta: {
     ...
   },
   data: [
       {entity},
       {entity},
       ...
   ]
}

not [ {entity}, {entity}, {entity}, ... ] style so much...

here's one example

So what we might missed here is some kind of convince way to modify the type of LIST data.

18601673727 avatar Dec 04 '16 08:12 18601673727