Skip to content

tengattack/cronet.js

Repository files navigation

Cronet.js

Cronet's native API bindings for Node.js.

Installation

This native addon uses CMake.js to build when package install.

So we will need to fulfill its requirements at first.

npm install cronet

Usage

const { Buffer } = require('node:buffer')
const cronetjs = require('cronet')
const {
  CronetEngineParams,
  CronetEngine,
  CronetExecutor,
  CronetUrlRequestCallback,
  CronetUrlRequestParams,
  CronetUrlRequest,
} = cronetjs

// dynamic load library
CronetEngine.loadLibrary('libcronet.so')

const params = new CronetEngineParams()
params.enableQuic = true // by default
const engine = new CronetEngine()
console.log('CronetEngine version: ' + engine.versionString)
engine.startWithParams(params)

const executor = new CronetExecutor()
executor.start()

function newRequest(url, timeout = 2000) {
  return new Promise((resolve, reject) => {
    const urlReq = new CronetUrlRequest()

    let body = null

    let t = setTimeout(function () {
      if (!t) {
        return
      }
      console.log('Request timeout.')
      t = null
      urlReq.cancel()
    }, timeout)

    const done = function () {
      if (t) {
        clearTimeout(t)
        t = null
      }
      resolve(body)
    }

    const urlReqParams = new CronetUrlRequestParams()
    urlReqParams.httpMethod = 'GET'
    urlReqParams.disableCache = true

    const urlCallback = new CronetUrlRequestCallback()
    urlCallback.onRedirectReceived = function (request, info, newLocationUrl) {
      console.log('onFollowRedirect: ' + info.httpStatusCode + ' ' + newLocationUrl)
      request.followRedirect()
    }
    urlCallback.onResponseStarted = function (request, info) {
      console.log('onResponseStarted: ' + info.url
        + ' ' + info.negotiatedProtocol
        + ' ' + info.httpStatusCode + ' ' + info.httpStatusText)

      console.log('All headers:')
      const allHeadersListSize = info.allHeadersListSize()
      for (let i = 0; i < allHeadersListSize; i++) {
        const header = info.allHeadersListAt(i)
        console.log({ name: header.name, value: header.value })
      }

      let buffer = new cronetjs.CronetBuffer()
      // Create and allocate 32kb buffer.
      buffer.initWithAlloc(32 * 1024)
      // Started reading the response.
      request.read(buffer)
    }
    urlCallback.onReadCompleted = function (request, info, buffer, bytesRead) {
      console.log('onReadCompleted, bytes read: ' + bytesRead)
      const bytes = buffer.data.slice(0, bytesRead)
      if (!body) {
        body = Buffer.from(bytes)
      } else {
        body = Buffer.concat([body, bytes])
      }
      // Continue reading the response.
      request.read(buffer)
    }
    urlCallback.onSucceeded = function (request, info) {
      console.log('onSucceeded')
      done()
    }
    urlCallback.onFailed = function (request, info, error) {
      console.log('onFailed, message: ' + error.message
        + ', error_code: ' + error.errorCode
        + ', internal_error_code: ' + error.internalErrorCode)
      done()
    }
    urlCallback.onCanceled = function (request, info) {
      console.log('onCanceled')
      done()
    }

    urlReq.initWithParams(engine, url, urlReqParams, urlCallback, executor)
    urlReq.start()
  })
}

async function main() {
  await newRequest('https://google.com/', 2000)
  executor.shutdown()
  engine.shutdown()
}

main()

About

Cronet Node.js bindings

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published