sasa1977 / site_encrypt

Integrated certification via Let's encrypt for Elixir-powered sites
MIT License
471 stars 34 forks source link

Is it possible to use site_encrypt with Plug instead of Phoenix? #24

Open ericmj opened 3 years ago

ericmj commented 3 years ago

I cannot find any documentation for it. It doesn't seem technically impossible to use with Plug directly but it doesn't seem supported when reading through the docs and code. If it is already possible then I would appreciate some pointers to put me in the right direction.

If it is not currently possible I would be willing to contribute if you want to add support for it, but some guidance on how you would want it work would be appreciated before I start.

sasa1977 commented 3 years ago

Yeah, Plug is currently not supported out of the box. I agree with you that technically it should be possible. The code is mostly designed to be independent of Phoenix. Unless I missed something, the only two modules which should depend on Phoenix are SiteEncrypt.Phoenix and SiteEncrypt.Phoenix.Test.

One problem is that SiteEncrypt.Phoenix contains some logic which should be common for all adapters. If you're not in a big hurry I could do a minor initial refactoring of that (perhaps I can make it tomorrow or at the latest by the end of the week), with the hope that your contribution would "only" require writing SiteEncrypt.Plug, SiteEncrypt.Plug.Test`, and include the related tests. I doubt that it will be that straightforward, but I can't think of possible issues at the moment, so it's something that needs to be explored through the code.

How does that sound?

ericmj commented 3 years ago

Thanks for your response. That sounds like a good plan, please ping me when your refactoring is done.

sasa1977 commented 3 years ago

So I've pushed minor refactoring in the branch support_plug.

This branch introduces a new module called SiteEncrypt.Adapter which contains the common logic for all adapters. It's currently not documented, because the interface might change while support for Plug is added.

Basically you need to include use SiteEncrypt.Adapter in the adapter module (e.g. SiteEncrypt.Plug), and implement the two required callback functions. You can look into SiteEncrypt.Phoenix for inspiration

These callback functions need to return the following:

  1. Site encrypt configuration (see docs for SiteEncrypt.configure/1)
  2. child_spec for starting the site
  3. HTTP port of the site

The consequence of 3 is that the child_spec in 2 must start two plug sites, one for http and another for https, which basically means that the childspec should describe a supervisor which starts the two sites as its children.

You'll notice that Adapter.start_link and callback functions accept a SiteEncrypt.id. This is an arbitrary term which uniquely identifies the site instance. The Phoenix adapter uses the endpoint module for this, since AFAIK Phoenix doesn't support dynamic instances of the same endpoint.

My proposal is to try implementing a prototype hardcoded plug adapter, i.e. a module which combines the new Adapter with a hardcoded plug server (e.g. an echo server or something comparably simple), using some hardcoded id (e.g. module name). This would help us validate the existing interface, and adapt it if needed. Also, this implementation would be used as a starting point for defining a generic interface for the plug adapter.

To use the new implementation in tests, you'll need a modified version of SiteEncrypt.Phoenix.Test. There's perhaps potential to have a single generic test module, but my proposal is to initally copy-paste this code into a new test module and tweak it to support the new adapter. It's not a lot of code (about 50 LOC).

My feeling is that compared to Phoenix, Plug will be somewhat more complicated to support. Phoenix made some things easier because:

  1. It takes care of running multiple sites (http & https)
  2. The endpoint is always a plug builder
  3. It's a singleton

With Plug we will probably need to do more work, but I'm not certain on the exact details, which is why I'm proposing the hardcoded experiment first.

Let me know what you think, and feel free to ask if you have any questions.

riccardomanfrin commented 2 years ago

@sasa1977 could you provide the sample code required for integrating with Plug similarly to what done for Phoenix?

thanks