Binding WebAssembly modules

For uploading WebAssembly modules you will need to make a call to the following API endpoint:

PUT /zones/:zone_id/workers/script (Self-serve API)

or

PUT /accounts/:account_id/workers/scripts/:scriptName (Enterprise API)

First, you will need to submit the metadata about which bindings you will be sending.

For example, here we’ll be storing the following metadata in metadata.json

{
  "body_part": "script",
  "bindings": [
    {
      "name": "mywasm",
      "type": "wasm_module",
      "part": "wasmprogram"
    }
  ]
}

This JSON must be uploaded in a multipart/form-data part named metadata. This is the only reserved part name in the PUT payload; it in turn refers to other multipart/form-data parts which may be named anything other than metadata.

Metadata properties:

  • body_part: the name of the multipart/form-data part that contains the Worker’s main script.
  • bindings: a list of bindings we will be attaching (this is where the WASM modules will go).

WebAssembly binding properties:

  • name: the name of the variable that will be used in the script. For example, if the name if defined as mywasm, the function will be called as such.
  • type: the type for uploading WebAssembly modules will always be wasm_module.
  • part: the name of the multipart/form-data part that contains the WebAssembly file (such as mywasm.wasm).

Example:

In the example below, we will be uploading a WebAssembly module called isqrt which defines an inverse square root.

Next, I define my metadata in metadata_wasm.json.

metadata_wasm.json:

{
  "body_part": "script",
  "bindings": [
    {
      "name": "isqrt",
      "type": "wasm_module",
      "part": "wasmprogram"
    }
  ]
}

In my Worker, I instantiate the WebAssembly module instance I will be using.

let instance = new WebAssembly.Instance(isqrt, {})

To utilize the function defined by the WASM module, I then use instance.exports (which from my module includes the _Z7Q_rsqrtf function:

let squareroot = instance.exports._Z7Q_rsqrtf(number)

Full Worker (script_sqrt.js):

let instance = new WebAssembly.Instance(isqrt, {})
  
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

/**
 * Fetch and log a request
 * @param {Request} request
 */
async function handleRequest(request) {
  let squareroot = instance.exports._Z7Q_rsqrtf(1)
  return new Response(squareroot, {status: 200})
}

API call:

In the API call to upload the script, I attach:

  • metadata: to define the bindings I will be sending through.
  • the WASM file
  • the script itself

Self-serve API:

curl -sv -X PUT "https://api.cloudflare.com/client/v4/zones/:zone_id/workers/script" \
-H "X-Auth-Email:YOUR_CLOUDFLARE_EMAIL" \
-H "X-Auth-Key:ACCOUNT_AUTH_KEY" \
-F '[email protected]_wasm.json;type=application/json' \
-F '[email protected];type=application/wasm' \
-F '[email protected]_sqrt.js;type=application/javsacript'

Enterprise API:

curl -sv -X PUT "https://api.cloudflare.com/client/v4/accounts/:account_id/workers/scripts/sqrt" \
-H "X-Auth-Email:YOUR_CLOUDFLARE_EMAIL" \,
-H "X-Auth-Key:ACCOUNT_AUTH_KEY" \
-F '[email protected]_wasm.json;type=application/json' \
-F '[email protected];type=application/wasm' \
-F '[email protected]_sqrt.js;type=application/javsacript'