Why don't apollo-client's GraphQL queries appear in Chrome's XHR Network filter? - xmlhttprequest

I'm using apollo-client, and I've just noticed that my GraphQL queries don't appear on the list of Network calls when the XHR filter is active.
How is this possible? GQL is just a set of semantics on top of regular old HTTP, right? It's not like a JS library can introduce a whole new networking capability.
In the first image below, you see me filtering for requests with "gra" in them; two appear: the OPTIONS call, and then the POST (which is the real meat). In the second image, I additionally filter by XHRs; the POST is gone.
The "XHR" filter says it captures "XHR and Fetch". The only alternative I can think of would be dynamically adding <script> tags to the document, and I very much doubt that's how apollo-client is managing things.
I don't know what the "json" Type is. The docs for the DevTools don't mention that type.

I think the reason for this is that Chrome's fetch capability is not simply sugar on top of the age-old XMLHttpRequest capability, and the filter option in the DevTools (which says "XHR") is either not built or not designed as an umbrella "asynchronous request" filter. I hope they change that, especially since the Type column in the Network panel can still be used to differentiate between the two.
If I had to speculate, I'd say the behavior we observe flows from the way the Network tab hooks into the underlying networking code, and fetch calls don't travel the relevant portion of the codepath that XHR does. As supporting evidence, I offer this SO answer, which highlights functional differences between XHR & fetch that might readily be explained by their being entirely separate code. (It's also possible some of these differences are a result of the fetch spec explicitly calling for behavior different from XHR.)
Finally, I'd add that we probably only noticed this with Apollo's GQL tools because apollo-client was created in a post-XHR world, and may be one of the first libraries we worked with that prefers fetch over XHR rather than using an XHR polyfill.

Related

Appropriate REST design for data export

What's the most appropriate way in REST to export something as PDF or other document type?
The next example explains my problem:
I have a resource called Banana.
I created all the canonical CRUD rest endpoint for that resource (i.e. GET /bananas; GET /bananas/{id}; POST /bananas/{id}; ...)
Now I need to create an endpoint which downloads a file (PDF, CSV, ..) which contains the representation of all the bananas.
First thing that came to my mind is GET /bananas/export, but in pure rest using verbs in url should not be allowed. Using a more appropriate httpMethod might be cool, something like EXPORT /bananas, but unfortunately this is not (yet?) possible.
Finally I thought about using the Accept header on the same GET /bananas endpoint, which based on the different media type (application/json, application/pdf, ..) returns the corresponding representation of the data (json, pdf, ..), but I'm not sure if I am misusing the Accept header in this way.
Any ideas?
in pure rest using verbs in url should not be allowed.
REST doesn't care what spelling conventions you use in your resource identifiers.
Example: https://www.merriam-webster.com/dictionary/post
Even though "post" is a verb (and worse, an HTTP method token!) that URI works just like every other resource identifier on the web.
The more interesting question, from a REST perspective, is whether the identifier should be the same that is used in some other context, or different.
REST cares a lot about caching (that's important to making the web "web scale"). In HTTP, caching is primarily about re-using prior responses.
The basic (but incomplete) idea being that we may be able to re-use a response that shares the same target URI.
HTTP also has built into it a general purpose mechanism for invalidating stored responses that is also focused on the target URI.
So here's one part of the riddle you need to think about: when someone sends a POST request to /bananas, should caches throw away the prior responses with the PDF representations?
If the answer is "no", then you need a different target URI. That can be anything that makes sense to you. /pdfs/bananas for example. (How many common path segments are used in the identifiers depends on how much convenience you will realize from relative references and dot segments.)
If the answer is "yes", then you may want to lean into using content negotiation.
In some cases, the answer might be "both" -- which is to say, to have multiple resources (each with its own identifier) that return the same representations.
That's a normal thing to do; we even have a mechanism for describing which resource is "preferred" (see RFC 6596).
REST does not care about this, but the HTTP standard does. Using the accept header for the expected MIME type is the standard way of doing this, so you did the right thing. No need to move it to a separate endpoint if the data is the same just the format is different.
Media types are the best way to represent this, but there is a practical aspect of this in that people will browse a rest API using root nouns... I'd put some record-count limits on it, maybe GET /bananas/export/100 to get the first 100, and GET /bananas/export/all if they really want all of them.

How do I design a REST call that is just a data transformation?

I am designing my first REST API.
Suppose I have a (SOAP) web service that takes MyData1 and returns MyData2.
It is a pure function with no side effects, for example:
MyData2 myData2 = transform(MyData myData);
transform() does not change the state of the server. My question is, what REST call do I use? MyData can be large, so I will need to put it in the body of the request, so POST seems required. However, POST seems to be used only to change the server state and not return anything, which transform() is not doing. So POST might not be correct? Is there a specific REST technique to use for pure functions that take and return something, or should I just use POST, unload the response body, and not worry about it?
I think POST is the way to go here, because of the sheer fact that you need to pass data in the body. The GET method is used when you need to retrieve information (in the form of an entity), identified by the Request-URI. In short, that means that when processing a GET request, a server is only required to examine the Request-URI and Host header field, and nothing else.
See the pertinent section of the HTTP specification for details.
It is okay to use POST
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
It's not a great answer, but it's the right answer. The real issue here is that HTTP, which is a protocol for the transfer of documents over a network, isn't a great fit for document transformation.
If you imagine this idea on the web, how would it work? well, you'd click of a bunch of links to get to some web form, and that web form would allow you to specify the source data (including perhaps attaching a file), and then submitting the form would send everything to the server, and you'd get the transformed representation back as the response.
But - because of the payload, you would end up using POST, which means that general purpose components wouldn't have the data available to tell them that the request was safe.
You could look into the WebDav specifications to see if SEARCH or REPORT is a satisfactory fit -- every time I've looked into them for myself I've decided against using them (no, I don't want an HTTP file server).

How to organize endpoints when using FeathersJS's seemingly restrictive api methods?

I'm trying to figure out if FeathersJS suits my needs. I have looked at several examples and use cases. FeathersJS uses a set of request methods : find, get, create, update, patch and delete. No other methods let alone custom methods can be implemented and used, as confirmed on this other SO post..
Let's imagine this application where users can save their app settings. Careless of following method conventions, I would create an endpoint describing the action that is performed by the user. In this case, we could have, for instance: /saveSettings. Knowing there won't be any setting-finding, -creation, -updating (only some -patching) or -deleting. I might also need a /getSettings route.
My question is: can every action be reduced down to these request methods? To me, these actions are strongly bound to a specific collection/model. Sometimes, we need to create actions that are not bound to a single collection and could potentially interact with more than one collection/model.
For this example, I'm guessing it would be translated in FeathersJS with a service named Setting which would hold two methods: get() and a patch().
If that is the correct approach, it looks to me as if this solution is more server-oriented than client-oriented in the sense that we have to know, client-side, what underlying collection is going to get changed or affected. It feels like we are losing some level of freedom by not having some kind of routing between endpoints and services (like we have in vanilla ExpressJS).
Here's another example: I have a game character that can skill-up. When the user decides to skill-up a particular skill, a request is sent to the server. This endpoint can look like POST: /skillUp What would it be in FeathersJS? by implementing SkillUpService#create?
I hope you get the issue I'm trying to highlight here. Do you have some ideas to share or recommendations on how to organize the API in this particular framework?
I'm not an expert of featherJs, but if you build your database and models with a good logic,
these methods are all you need :
for the settings example, saveSettings corresponds to setting.patch({options}) so to the route settings/:id?options (method PATCH) since the user already has some default settings (created whith the user). getSetting would correspond to setting.find(query)
To create the user AND the settings, I guess you have a method to call setting.create({defaultOptions}) when the user CREATE route is called. This would be the right way.
for the skillUp route, depends on the conception of your database, but I guess it would be something like a table that gives you the level/skills/character, so you need a service for this specific table and to call skillLevel.patch({character, level})
In addition to the correct answer that #gui3 has already given, it is probably worth pointing out that Feathers is intentionally restricting in order to help you create RESTful APIs which focus on resources (data) and a known set of methods you can execute on them.
Aside from the answer you linked, this is also explained in more detail in the FAQ and an introduction to REST API design and why Feathers does what it does can be found in this article: Design patterns for modern web APIs. These are best practises that helped scale the internet (specifically the HTTP protocol) to what it is today and can work really well for creating APIs. If you still want to use the routes you are suggesting (which a not RESTful) then Feathers is not the right tool for the job.
One strategy you may want to consider is using a request parameter in a POST body such as { "action": "type" } and use a switch statement to conditionally perform the desired action. An example of this strategy is discussed in this tutorial.

How to consume a graphql API with Vue

Pretty simple you'd think given the popularity of both, but I am encountering a few hurdles.
I am using scaphold.io to be able to quickly show off a working UI. That is, if Vue can interact with Scaphold.
I have investigated two resources:
https://github.com/kristianmandrup/vue2-apollo-scaphold
Which seems to be a Scaphold production. Tried it. Many, many vague bugs.
Then there is also:
https://github.com/Akryum/vue-apollo
But this is too much. I don't need a server, the server is on Scaphold.
I also tried building the whole thing up by using the tutorial on howtographql, but this one is also outdated.
Ideally I want to instantiate an as up to date Vue 2 app using (I guess) the npm vue-cli, then install only the required apollo (or whatever, but I guess apollo) add-ons that I need. The minimum.
Shouldn't be too hard, I'll figure it out eventually, but some help is more than welcome.
You can consume a graphql api using your favorite regular request module (ajax, fetch, axios). Take the scalphold docs for example, but in the callback do this.vueUserData = body.data.getUser;
instead of
console.log(JSON.stringify(body, null, 2));
(edited to add one gotcha I remembered: if you encounter a problem where the callback doesn't know that this is supposed to be the component, you can do var self = this before the request function, then reference self.vueUserData instead.)

Does Dojo framework support grouping/bunching of same type of commands to avoid multiple request to server?

I know, we can do grouping of same kind of Ajax requests to server.
But just wanted to know if Dojo supports this or let us know if this feature doesn't depend upon Dojo framework or jquery...
Depending on the type of request you do, and how response headers are set, some kinds of AJAX requests can be cached by the browser itself, just like it would cache a normal webpage.
Outside of the browser caching stuff, I don't know of any framework that does caching at the request level like that. So, if you need a request to not be repeated the only way to be sure is to not issue the request in the first place.
In Dojo's case, for example, it is quite common to issue AJAX requests via something like dojo/store/JsonRest instead of doing them by hand. In this case it is quite easy to use something like a dojo/store/Cache to add a cacheing layer in front of the JsonRest store.
http://livedocs.dojotoolkit.org/dojo/store/Cache
http://www.sitepen.com/blog/2011/02/15/dojo-object-stores/