depot / node-spiffe

A SPIFFE Workload API client for Node.js
https://www.npmjs.com/package/spiffe
MIT License
3 stars 0 forks source link

node-spiffe can't be used inside Express? #55

Open phelicksg opened 4 days ago

phelicksg commented 4 days ago

Hi,

apologies if this is a newbie mistake, as I'm not very fluent in Express/Node yet. There is one example which works great, when used standalone. However, that example relies on using the "import" statement, which is not allowed when used in an Express app. Instead, one would have to rewrite the example to use the "require" statement.

I am banging my head against the wall with the line:

for await (const message of rpc.responses) {

I've changed the first lines to:

var spiffe = require ('spiffe');
// Connect to a specific endpoint
const client = spiffe.createClient('unix:///tmp/spire-agent/public/api.sock')

// Read x509 credentials from Workload API
const rpc = client.fetchX509SVID()

for await (const message of rpc.responses) {

[...]

Which renders the error:

usr/src/app/bad.js:14
for await (const message of rpc.responses) {
    ^^^^^

SyntaxError: Unexpected reserved word
    at wrapSafe (node:internal/modules/cjs/loader:1469:18)
    at Module._compile (node:internal/modules/cjs/loader:1491:20)
    at Module._extensions..js (node:internal/modules/cjs/loader:1691:10)
    at Module.load (node:internal/modules/cjs/loader:1317:32)
    at Module._load (node:internal/modules/cjs/loader:1127:12)
    at TracingChannel.traceSync (node:diagnostics_channel:315:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:217:24)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:166:5)
    at node:internal/main/run_main_module:30:49

Node.js v22.9.0

Obviously I am doing something wrong, but this is not trivial. Do you think you could provide a short example that uses require instead of import to use the SPIFFE library? That would be super appreciated. Thanks so much in advance.

jacobwgillespie commented 3 days ago

Hey, no worries!

So the issue here is actually the await in for await - that's a JavaScript language feature that loops over an "async iterable", which is basically an iterable (object that produces multiple values) that produces each next value as a promise that needs to be await'd. Kinda like a stream of values. In the example, for await (const message of rpc.responses) basically says "for each response from the API".

Since it's using await though, you will likely need to run it inside an async function. There is something called "top level await" support that lets you use await outside of async functions, but it's experimental in the latest versions of Node.

That could look something like this:

const spiffe = require('spiffe');

// Connect to a specific endpoint
const client = spiffe.createClient('unix:///tmp/spire-agent/public/api.sock')

async function main() {
  // Read x509 credentials from Workload API
  const rpc = client.fetchX509SVID()

  for await (const message of rpc.responses) {
    ...
  }
}

main().catch(err => {
  console.error(err)
})

Basically you will want to use the for await inside of an async function, either a new one you make or an existing one in your codebase.

import vs require is a whole separate topic , but this library should support both ways the same.