xogroup / toki-discussion

Discussion and documents for the toki project
3 stars 0 forks source link

Role of toki-methods regarding http response sending #1

Open WesTyler opened 7 years ago

WesTyler commented 7 years ago

Pulling this line of discussion into an issue rather than in-line comments in a merged PR.

"Archived" comments below came from this PR

WesTyler 13 minutes ago • edited Member

@dhinklexo does calling something like response.send(payload) from within the method (like toki-method-http) simply attach that payload to the response that will eventually be sent by Toki? Or does it actually fire off the response object back to the client?

Basically do the toki plugins act like hapi prerequest handlers/decorators, or like the actual request handlers?

WesTyler 12 minutes ago Member

Or is this just a response object that is sent back to Toki to map to the main response and runtime context?

dhinklexo 9 minutes ago Member

(Context) This is just a copy of the bridge response/request API

(Answer) It looks like that IS the current behavior. Whether or not that's the desired behavior on the other hand..

WesTyler 4 minutes ago Member

My understanding from our initial talks about toki-method-http and toki-method-rabbit is that the method should define the shape of its result (via templated config) and do 2 things:

  1. pass that response back to toki, which will add it to the runtime context under the action's name property. future potential actions now have access to this mapped result.
  2. modify the "main" response object without sending it back to the client. This way toki can build up the main response by running it through all of the methods, then at the end send the total hydrated response back to the requesting client.
dhinklexo commented 7 years ago

So there are two different kinds of cases:

  1. toki-method-proxy - "I want full access to the real underlying request/response"
  2. toki-method-http - "I just want to pass back some data and let you assemble it"

Our current case seems fine for (1) but not (2). Could we, instead of passing Request/Response to the method, bind to it's context a number of different ways of responding?

WesTyler commented 7 years ago

Regarding my expectation of #2 above, especially in the context of toki-hapi-bridge, this looks a lot like the request decoration that hapi provides to prerequest handlers via the response object :

Note that prerequisites do not follow the same rules of the normal reply interface. In all other cases, calling reply() with or without a value will use the result as the response sent back to the client. In a prerequisite method, calling reply() will assign the returned value to the provided assign key.... To force the return value as the response and ends the request lifecycle, use the reply().takeover() method.

^^ from here

WesTyler commented 7 years ago

So it sounds to me like the default behavior should mirror the response decoration behavior that Hapi prereqs follow, and the use case for toki-method-proxy is a special snowflake that would in the above example use the .takeover() method.

dhinklexo commented 7 years ago

Should we facade that in the same way as Hapi, or divorce it and have it be a different kind of thing?

The facade seems magical. I'm not a big fan of magical. On the other hand, it also lets a method be used in two different fashions - fully and blindly, or as part of a flow.

Keeping the two different kind of responses divorced allows the method to have control and keeps things more explicit.

I'd be tempted to have the context be something like this:

{
  server: { request, response }
  respond: ()=>{... //pass data back to Toki for it to assemble
}
WesTyler commented 7 years ago

I like divorcing it. I agree the Hapi-style facade was a bit jarring at first blush. I get that it makes handlers interchangeable between prereqs and req handlers, but that doesn't mirror our needs here.

I would be on board with something like your split context.

My followup concerns would then be delegation of responsibility and the response lifecycle: In the case of toki-method-proxy, which of these would occur?

  1. method-proxy does its thing, builds the response payload, calls context.server.response.send(payload)
  2. the response is immediately sent from the method-proxy plugin
  3. toki gets the resolved promise / callback / result from method-proxy and proceeds to the next hypothetical action in the config list

OR

  1. method-proxy does its thing, builds the response payload, calls context.server.response.send(payload)
  2. toki gets the resolved promise / callback / result from method-proxy and proceeds to the next hypothetical action in the config list.
  3. At the end of the actions list, toki sends the response from step 1.
dhinklexo commented 7 years ago

My first thought would be option A, with the risk that you can have an invalid config where future actions try to send data to an already closed request/response. It would be odd behavior for the proxy to pass back to Toki (and if it wanted to do that, it should just use the respond() method instead of server.*)

WesTyler commented 7 years ago

Sounds good. Just wanted to have a clear understanding of the response lifecycle so I don't get confused again.

Thanks!

dhinklexo commented 7 years ago

Tbh, I don't think we ever really nailed this down until now. I was just as confused.

WesTyler commented 7 years ago

I'm going to leave this open for reference until toki-method-http and toki-method-proxy are done.

dhinklexo commented 7 years ago

Also so that @lamchakchan can chime in

WesTyler commented 7 years ago

Meh.

Haha, just kidding. Yes, also that.