Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading WASM plugin using http-wasm without Go? #6

Open
mobileskyfi opened this issue Jun 7, 2024 · 4 comments
Open

Loading WASM plugin using http-wasm without Go? #6

mobileskyfi opened this issue Jun 7, 2024 · 4 comments

Comments

@mobileskyfi
Copy link

mobileskyfi commented Jun 7, 2024

Not sure where to file this.

Just for fun, I've been tried building Traefik WASM plugin using Grain. I'm still working on the http-wasm binding and type-mapping, but it loads/runs as Grain-based WASM plugin from/pluginsLocal/src/grain/plugin.wasm.

While not ready to publish anything on the Traefik Plugin Catalog, I did add the "traefik-plugin" GitHub tag to this project: https://github.com/tikoci/traefik-wasm-grain with following .traefik.yml:

displayName: traefik-wasm-grain
type: middleware
runtime: wasm
iconPath: icon.png
summary: Experimental plugin using WASM and grain-lang.org, directly using http-wasm ABI
testData:
  Headers:
    Foo: Bar

And docs suggest I should have gotten an automated #3 "Plugin Analyzer ... problem" bug reports by virtue of the tag. But that never happened. I even added a tagged release to project – just to trigger something – since I'm not 100% the .traefik.yml is right.

Perhaps the "Plugin Catalog" also check to project type is "Go" – since GitHub flags tikoci/traefik-wasm-grain as a Makefile project?
image

Not urgent here. But be nice to know something could be published to avoid file copies/Dockerfile-mod/etc to "localPlugins".

@mobileskyfi
Copy link
Author

I figure this out. It was the GitHub language.

Adding this in .gitattributes fix it:

# Grain is Go for Traefik
*.gr linguist-language=go

# see https://github.com/github-linguist/linguist/blob/master/docs/overrides.md

Since this project is kinda the only place where building a WASM plugin is documented, I filled it here. I don't know the traefik plumbing/process, my guess is piceus
searchQuery = "topic:traefik-plugin language:Go archived:false is:public"

While Grain is pretty esoteric, I'd imagine someone will build one of these in Rust/etc soon enough.

Perhaps there should be a new GitHub tag like "traefik-wasm-plugin" (or whatever)?

@nihaopaul
Copy link

I figure this out. It was the GitHub language.

Adding this in .gitattributes fix it:

Grain is Go for Traefik

*.gr linguist-language=go

see https://github.com/github-linguist/linguist/blob/master/docs/overrides.md

Since this project is kinda the only place where building a WASM plugin is documented, I filled it here. I don't know the traefik plumbing/process, my guess is piceus searchQuery = "topic:traefik-plugin language:Go archived:false is:public"

While Grain is pretty esoteric, I'd imagine someone will build one of these in Rust/etc soon enough.

Perhaps there should be a new GitHub tag like "traefik-wasm-plugin" (or whatever)?

Did you manage to find one? I've spent a few hours today trying to get rust version of wasm compiled and loaded. I've got the outline so far but trying to enable logging pass through but I'm a bit of a noob when it comes to rust so I'm also interested in examples: https://github.com/nihaopaul/traefik-rust-wasm-plugin

@mobileskyfi
Copy link
Author

mobileskyfi commented Oct 30, 2024

Did you manage to find one?

No, only Go examples for http-wasm ABI used by Traefik. Given you can already write a Traefik plugin in Go, the indirection of Go-based WASM is actually less useful... And... https://http-wasm.io only has the TinyGo example.

The underlying issue is that http-wasm that Traefik uses is not friendly with wasm-bindgen and/or wit-bindgen Rust likes... And with a .wit file... all this be easier in Rust, but the http-wasm folks seem to have philosophical problems with a .wit file... so you just get commented .wat file.

What this means is http-wasm ABI needs to be explicitly defined in Rust to be callable. So to make a log() call to http-wasm/Traefik from Rust...I think your code need some #[link()] things...

 #[link(wasm_import_module)]
extern log(level: i32, msg: i32, len: i32) 

And repeated for rest of thethe http-wasm ABI functions exposed by Traefik (or at least the ones you plan to use). This be similar to what I had to do for Grain so the the handler can perform operations like log() or set_header_value().

But since msg is a pointer, that also need to managed in your code. And all of which is why I didn't try, and my Rust knowledge is pretty superficial. But I did get Grain working, which largely involved mapping the .wat file, by hand. I added another high-level wrapper "extern" things to deal with marshaling strings to deal with this in Grain: https://github.com/tikoci/traefik-wasm-grain/tree/main

Also, you can use wasm2wat to see what Rust generated, and compare to the signatures in the .wat file from http-wasm - as they should look the same.

But...some Rust example be useful here — as noted, if you're writing Go, a real plugin would seem to be a better plan than WASM. You have some rust code you want to run, well, now WASM support be more useful in Traefik.

@nihaopaul
Copy link

Did you manage to find one?

No, only Go examples for http-wasm ABI used by Traefik. Given you can already write a Traefik plugin in Go, the indirection of Go-based WASM is actually less useful... And... https://http-wasm.io only has the TinyGo example.

The underlying issue is that http-wasm that Traefik uses is not friendly with wasm-bindgen and/or wit-bindgen Rust likes... And with a .wit file... all this be easier in Rust, but the http-wasm folks seem to have philosophical problems with a .wit file... so you just get commented .wat file.

What this means is http-wasm ABI needs to be explicitly defined in Rust to be callable. So to make a log() call to http-wasm/Traefik from Rust...I think your code need some #[link()] things...

 #[link(wasm_import_module)]
extern log(level: i32, msg: i32, len: i32) 

And repeated for rest of thethe http-wasm ABI functions exposed by Traefik (or at least the ones you plan to use). This be similar to what I had to do for Grain so the the handler can perform operations like log() or set_header_value().

But since msg is a pointer, that also need to managed in your code. And all of which is why I didn't try, and my Rust knowledge is pretty superficial. But I did get Grain working, which largely involved mapping the .wat file, by hand. I added another high-level wrapper "extern" things to deal with marshaling strings to deal with this in Grain: https://github.com/tikoci/traefik-wasm-grain/tree/main

Also, you can use wasm2wat to see what Rust generated, and compare to the signatures in the .wat file from http-wasm - as they should look the same.

But...some Rust example be useful here — as noted, if you're writing Go, a real plugin would seem to be a better plan than WASM. You have some rust code you want to run, well, now WASM support be more useful in Traefik.

Check out https://github.com/nihaopaul/traefik-rust-wasm-plugin/ I managed to spend a few days getting this to work. I use docker to load my wasm file once compiled. I've followed the http-wasm spec and made decisions such as dynamic buffers. And implemented the i32/i64s as per spec not the signed integers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants