Serve Templated HTML from Canister via HTTP

Hey everyone,

I’ve been poring over this forum + the docs + the wiki site for how I could accomplish the (seemingly) simple goal of serving a multi-page website from a canister.

To give an example, how would I go about serving an index.html that renders a page with Go to Linked Page, which links to another html page (linked.html, for instance; excuse my pedantry)?

To take the example up a notch, would I be able to use an HTML templating library to render dynamic, arbitrary HTML and send that back to the user? Would I be able to handle multipart/form POST requests to modify state in a canister? PATCH and DELETE requests? This approach would enable the classic web server approach to building applications, but with the benefits of running on the internet computer – not to mention that this is basic web technology.

Long story short, I would love to somehow build a canister that responds to http requests and returns http responses (in my case, HTML, though JSON etc would fit the bill as well… I’m wanting an HTMX, HATEOAS approach to building frontends).

My understanding is that the HTTP Gateway Protocol is implemented by Boundary Nodes, which essentially bridge HTTP <—> ICP. However, IIUC, canister devs do not have access to these gateways in the sense that we develop our code to run on them. I saw some icx-proxy related discussions, but I’m a bit lost on the discussion (especially since the repo is now archived). My understanding of the static asset canister is that it can only serve SPA’s via a single index.html entrypoint specified in a dfx.json, meaning front ends have to built with client-side-rendered applications such as React, Vue, etc. So, I’m guessing that a canister has to be created manually to handle what I’m talking about.

Would anyone happen to have a Rust proof-of-concept laying around?

Is it as simple as implementing http_request and http_request_update on various fn’s defined in my lib.rs, and returning HTML in the response body?

(also for more context, I’m wanting to see if there is an approach that doesn’t involve JS at all)

Currently working on something similar here (POC), an MVC like structure with HTMX. You can have a look a this.

but facing some CORS issue on inter-canister http calls, probably one of my last hurdle. Tried to tweak the .ic-assets.json without succes. Next step was to document the process’s and implement a light templating engin.

1 Like

Yes, all correct

For this you probably would have to implement something like Kyle’s certified-cache. It’s in Motoko, but probably could be ported to Rust relatively easily

If you’re willing to go through raw, then yes. Otherwise it’s a much more involved process because you have to do asset certification. Reason being that otherwise, because http_request is a query call and gets answered by a single replica, a malicious replica could respond with arbitrary, malicious code without anyone detecting it.

If you want to do certification (please only handle v2, deprecating v1 is already floating around as an idea), you can use this folder to copy/paste a lot of the implementation. We plan to turn it into a proper crate soon™, but it’ll probably be a while until it’s done. To test your implementation you can do it like this in unit test. If it passes this verification step then it’ll also pass on mainnet. The boundary nodes use the same crate under the hood

Here is my solution: GitHub - galaxydo/ic-sw-starter