How to run dat-node as a micro service?

230 Views Asked by At

UPDATE: Added the full server code. Notice that the route for static content is working fine, only the one relative to Dat fails. Also, I'm running node 10.8.0 with no transpiler or anything, server is ran with micro -l tcp://0.0.0.0:$PORT


I'm trying to run dat-node with Zeit micro. I have this micro service

const { send } = require('micro')
const Dat = require('dat-node')
const handler = require('serve-handler')
const { router, get, post } = require('microrouter')

const static = async (request, response) => {
  await handler(request, response, {
  // static app folder
  public: 'static',
    // javascript header for es modules
    headers: {
      source: '**/*.mjs',
      headers: [{
        key: 'Content-Type',
        value: 'text/javascript'
      }]
    },
    // no directory listing
    directoryListing: false
  })
}

const createGame = (request, response) => {
  Dat('./game', (err, dat) => {
    if (err) throw err

    let progress = dat.importFiles({watch: true})

    progress.on('put', function (src, dest) {
      console.log('Importing ', src.name, ' into archive')
    })

    dat.joinNetwork()

    send(response, 200, { key: dat.key.toString('hex') })
  })
}

const joinGame = (request, response) => {

}

module.exports = router(
  post('/game', createGame),
  post('/game/:game', joinGame),
  get('/*', static)
)

I just want to create a dat archive and return the public key, but when I call send I get this error

(node:2054) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:469:11)
    at send (/home/ubuntu/workspace/node_modules/micro/lib/index.js:72:8)
    at Dat (/home/ubuntu/workspace/index.js:35:5)
    at /home/ubuntu/workspace/node_modules/dat-node/index.js:112:9
    at apply (/home/ubuntu/workspace/node_modules/thunky/index.js:44:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)(node:2054) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)(node:2054) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

So, I'm not sure where the header is being sent, maybe I'm just handling Dat callback in a wrong way? not sure how to implement this service.

2

There are 2 best solutions below

1
On BEST ANSWER

The issue appears to be the usage of micro, not any issue with dat-node. When you are doing async work in micro, you need to use the async/await tools of Javascript (promises).

Here is the fixed code:

const createGame = async (request, response) => {
  var key = await new Promise((resolve) => {
    Dat('./game', (err, dat) => {
      if (err) throw err

      let progress = dat.importFiles({watch: true})

      progress.on('put', function (src, dest) {
        console.log('Importing ', src.name, ' into archive')
      })

      dat.joinNetwork()
      resolve(dat.key.toString('hex'))
    })
  })
  console.log('sending')
  send(response, 200, { key })
}
1
On

The snippet works if you export the function. Run with micro whatever.js and curl to localhost:3000 which should return the key.

const { send } = require('micro')
const Dat = require('dat-node')

module.exports = (request, response) => {
  Dat('./game', async (err, dat) => {
    if (err) throw err

    let progress = dat.importFiles({watch: true})

    progress.on('put', function (src, dest) {
      console.log('Importing ', src.name, ' into archive')
    })

    dat.joinNetwork()

    send(response, 200, { key: dat.key.toString('hex') })
 })
}