denali-js / core

An opinionated, ORM agnostic framework for building robust JSON APIs in Node
http://denalijs.org
Apache License 2.0
73 stars 14 forks source link

Content Negotiation story #170

Open acorncom opened 8 years ago

acorncom commented 8 years ago

When Denali responds to a request, it runs through the responder setup here (https://github.com/denali-js/denali/blob/master/lib/runtime/action.js#L251-L277), allowing data to be formatted differently depending on what the client was requesting.

Simple cases are handled already, but JSON-API's application/vnd.api+json Accept type is not super conducive to mapping down to a respondWithJsonApi method name. Instead of hard-coding the JSON-API accept type into Denali, it'd be nice to have serializers add a responderShorthand (or equivalently named method) that would allow Denali to "register" all respondWith names that might be used by the router.

This isn't fully fleshed out, but is mainly a placeholder for future iteration / thoughts.

davewasmer commented 8 years ago

Hmm, so thinking this out a bit more, not sure I'm in love with the idea of adding this to serializers anymore.

I think it's a fair assumption that serializers will correspond to one and only one media type, but the reverse may not be true. I could imagine a single media type used across an API, but having different base serializer types (perhaps a simple JSON serializer, and an embedded records serializer).

So if a single media type can trigger different serializers, storing these shorthands on the serializers doesn't feel like the right spot.

Perhaps we could hardcode some basic ones into the config, but let the consuming app add their own?

davewasmer commented 7 years ago

Some additional thoughts:

Mapping content types to responder method names is obviously not ideal - they don't camelCase very nicely or intuitively. In theory, serializers seem like a decent place to handle content-negotiation (serializers are responsible for how the data looks over the wire, which sounds exactly like content-negotiation).

The edge case here is that you may want to perform different business logic based on the content type (i.e. run a different action responder method, or at least vary a single responder methods behavior).

Rails handles this with the respond_to method, something we could probably look to for some inspiration.

davewasmer commented 7 years ago

We could do something like

class MyAction extends Action {

 respondTo: {
    xml() {...},
    'foo/bar'() {...}
 }