currently i try to develop a app which is unsing the caddy api to establish configuration changes dynamically during runtime from another golang application.
The application should be able to change certain things on a running caddy instance using its api. The app is offering some abstracted rest api with certain other things which are not related to the reverseproxy on a single server.
Maybe also because im quite new to golang i’m having some difficulties regarding the mapping of the dynamic caddy datastructures during runtime.
The idea is to hide certain fields for the user of the original caddy API and offer only a few features and not all fieldsexposed because they will be preconfigured and just internal.
I thougth about just reusing the caddy structures (e.g. caddytls.acmeissuer) in the client code of the golang application and unmashall the data directy in the respective structures. But its not that easy because of a lot of polymorhic which makes the parsing verry complex.
I would like to avoid to “reinvent the wheel” and looking for something which can be reused. I was thinking caddy has to deal with simmilar problems even if it is in reverse order.
A “internal issuer” is quite easy to unmarshal from the received json request but when there is for example “acme issuer” its getting komplex.
What could be the best way to archiving this kind of abstraction of the caddy API?
I want to be able to do all necessary request ( GET / POST / PUT…) to caddy via the standard api.
Example:
“GET”, “apps/tls/automation” to caddy.socket
unmarshal request into caddy sturctures
map relevant data into structures represented by the client application api (api schemas of webserver endpoints)
I need some inspiration and feedback as well. Maybe the idea is dump?! How would you deal with that? What would be youre recommendation?
You can reuse the data types that Caddy does if you’re writing Go. The “polymorphic” fields, which are module fields, get unmarshaled into json.RawMessage. You can then proceed to unmarshal that depending on the type/value that fills that space. The tricky part is knowing what type to unmarshal each module config into.
The way Caddy unmarshals module JSONs dynamically is in context.go in the LoadModule()-family-of-functions:
I admit it is not pretty. But it works quite well. Unfortunately it doesn’t generalize well outside of Caddy. Maybe it could be refactored so that an exported API makes it easier to use outside of Caddy.
Thank you for your prompt reply and for your commitment to this excellent project. Your response was indeed helpful.
I was in search of a specific API, but it appears it’s not available at this time. It would be fantastic if the API could be released in the future. Additionally, optimizing the caddy implementation of the unmarshal operations with this approach could streamline the process, eliminating the need for any admissions though, in all fairness, there’s nothing to admit in the first place .
I’ll will take a look at the context.go and the LoadModule-functions.
im not sure if i understand your suggestion correct, would this be really a benefit? I also have to parse and interpret all responses in the respective data in my opinion.