hapipal / boilerplate

A friendly, proven starting place for your next hapi plugin or deployment
https://hapipal.com
183 stars 27 forks source link

Calling Plugin Route Handler from App Handler #66

Closed renjurajt closed 5 years ago

renjurajt commented 5 years ago
service-x/
├── lib/
│   ├── routes
│   ├── get-student.js
│       ├── new-student.js
│
├── server/

service-y/
├── lib/
├── server/

service-z/
├── lib/
├── server/

gateway-service/
├── lib/
│   ├── routes
│       ├── gw-get-student.js
│       ├── gw-new-student.js
│   ├── plugins
│       ├── service-x.js
│       ├── service-y.js
│       ├── service-z.js
├── server/

Service-x, y and z are micro services. "gateway-service" act as proxy/gateway service to all other services.

I want to add all the "x/y/z" services as a plugin to "gateway-service". And for that, I created files in "lib/plugins" directory and its registered successfully.

But I am not sure how do I call the "service-x" route handler from "gateway-service" handler. !!!!

Can you please help me on this?

I designed this way, so that initially i will deploy the App as one Monolithic app. If required I can deploy as individual micro service as well. Is this design is correct ?

devinivy commented 5 years ago

I don't know your exact needs, but this seems like a fine design to me! I think it's great that you're utilizing hapi plugins to have a flexible deployment, monolithic today and possibly micro-services in the future.

I'm interested to hear more about why you're trying to call one route handler from another, which is something I usually avoid. Route handlers are often coded with some assumptions from their route configuration—validation, payload/cookie parsing settings, authentication, assigned pres, etc., which can make them not very portable. That said, you have options!

  1. Rather than using handler A in handler B, consider extracting the logic in handler A out into a shared library, then using that library in both handlers. Based on the way you're using plugins, I think that schmervice would work very well for you. Because the gateway registers all your other plugins, the gateway would have access to all logic/services defined in those plugins via schmervice. For an example of using schmervice see the realworld example app: here and here.

  2. Use [server.inject()](https://github.com/hapijs/hapi/blob/master/API.md#server.inject()) to make a request "internally" to your server. Rather than using handler A in handler B, handler B would server.inject() a request to the route that has handler A. This is probably your simplest option and requires very little refactoring. It is a little hacky for hapi to generate a request to itself, and it does create some hard-to-track dependencies in your codebase. server.inject() is primarily meant for use in tests. But it certainly does work!

  3. I do not highly suggest this option, but it is another possibility. Because you're using haute-couture, you can require() the route configuration directly: require('service-x/lib/routes/get-student'). Then later in handler B: const response = await GetStudent.options.handler(request, h). Some weird stuff can happen with realms since this crosses plugin boundaries in a strange way, which would affect you if you're using schwifty or schmervice in your project. I would definitely be careful with this option if you consider it. server.inject() would probably be a safer alternative.

renjurajt commented 5 years ago

Thanks @devinivy. Let me try the option 1. Like you said it's better to avoid calling handler ..since it's designed for a specific purpose..