Git Product home page Git Product logo

json-rpc-engine's Introduction

@metamask/json-rpc-engine

⚠️ PLEASE READ ⚠️

This package has been migrated to our core monorepo, and this repository has been archived. Please note that all future development and feature releases will take place in the core repository.

A tool for processing JSON-RPC requests and responses.

Usage

const { JsonRpcEngine } = require('@metamask/json-rpc-engine');

const engine = new JsonRpcEngine();

Build a stack of JSON-RPC processors by pushing middleware to the engine.

engine.push(function (req, res, next, end) {
  res.result = 42;
  end();
});

Requests are handled asynchronously, stepping down the stack until complete.

const request = { id: 1, jsonrpc: '2.0', method: 'hello' };

engine.handle(request, function (err, response) {
  // Do something with response.result, or handle response.error
});

// There is also a Promise signature
const response = await engine.handle(request);

Middleware have direct access to the request and response objects. They can let processing continue down the stack with next(), or complete the request with end().

engine.push(function (req, res, next, end) {
  if (req.skipCache) return next();
  res.result = getResultFromCache(req);
  end();
});

By passing a return handler to the next function, you can get a peek at the result before it returns.

engine.push(function (req, res, next, end) {
  next(function (cb) {
    insertIntoCache(res, cb);
  });
});

If you specify a notificationHandler when constructing the engine, JSON-RPC notifications passed to handle() will be handed off directly to this function without touching the middleware stack:

const engine = new JsonRpcEngine({ notificationHandler });

// A notification is defined as a JSON-RPC request without an `id` property.
const notification = { jsonrpc: '2.0', method: 'hello' };

const response = await engine.handle(notification);
console.log(typeof response); // 'undefined'

Engines can be nested by converting them to middleware using JsonRpcEngine.asMiddleware():

const engine = new JsonRpcEngine();
const subengine = new JsonRpcEngine();
engine.push(subengine.asMiddleware());

async Middleware

If you require your middleware function to be async, use createAsyncMiddleware:

const { createAsyncMiddleware } = require('@metamask/json-rpc-engine');

let engine = new RpcEngine();
engine.push(
  createAsyncMiddleware(async (req, res, next) => {
    res.result = 42;
    next();
  }),
);

async middleware do not take an end callback. Instead, the request ends if the middleware returns without calling next():

engine.push(
  createAsyncMiddleware(async (req, res, next) => {
    res.result = 42;
    /* The request will end when this returns */
  }),
);

The next callback of async middleware also don't take return handlers. Instead, you can await next(). When the execution of the middleware resumes, you can work with the response again.

engine.push(
  createAsyncMiddleware(async (req, res, next) => {
    res.result = 42;
    await next();
    /* Your return handler logic goes here */
    addToMetrics(res);
  }),
);

You can freely mix callback-based and async middleware:

engine.push(function (req, res, next, end) {
  if (!isCached(req)) {
    return next((cb) => {
      insertIntoCache(res, cb);
    });
  }
  res.result = getResultFromCache(req);
  end();
});

engine.push(
  createAsyncMiddleware(async (req, res, next) => {
    res.result = 42;
    await next();
    addToMetrics(res);
  }),
);

Teardown

If your middleware has teardown to perform, you can assign a method destroy() to your middleware function(s), and calling JsonRpcEngine.destroy() will call this method on each middleware that has it. A destroyed engine can no longer be used.

const middleware = (req, res, next, end) => {
  /* do something */
};
middleware.destroy = () => {
  /* perform teardown */
};

const engine = new JsonRpcEngine();
engine.push(middleware);

/* perform work */

// This will call middleware.destroy() and destroy the engine itself.
engine.destroy();

// Calling any public method on the middleware other than `destroy()` itself
// will throw an error.
engine.handle(req);

Gotchas

Handle errors via end(err), NOT next(err).

/* INCORRECT */
engine.push(function (req, res, next, end) {
  next(new Error());
});

/* CORRECT */
engine.push(function (req, res, next, end) {
  end(new Error());
});

However, next() will detect errors on the response object, and cause end(res.error) to be called.

engine.push(function (req, res, next, end) {
  res.error = new Error();
  next(); /* This will cause end(res.error) to be called. */
});

Running tests

Build the project if not already built:

yarn build
yarn test

json-rpc-engine's People

Contributors

bitpshr avatar danfinlay avatar dependabot[bot] avatar frederikbolding avatar github-actions[bot] avatar gudahtt avatar kanthesha avatar kumavis avatar legobeat avatar majorlift avatar mrtenz avatar nir11 avatar niranjanabinoy avatar rekmarks avatar ryanml avatar whymarrh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json-rpc-engine's Issues

Dependencies Issue

The following "dependencies" should be reclassified as "devDependencies", as they are causing errors in upstream packages.

"@babel/preset-env": "^7.3.4"
"babelify": "^10.0.0"

Error example: ... json-rpc-engine > @babel/preset-env > @babel/[email protected]" has unmet peer dependency "@babel/core@^7.0.0-0".

Switch to Yarn

The project should be migrated to use Yarn:

  • for consistency with the rest of the org's packages
  • for less client bugs
  • for a more humane lockfile format

Please publish ES5 compiled version of json-rpc-engine

Hello,

I'm using json-rpc-engine from a create-react-app, and when building an production minified JS bundle (npm run build), I get an error:

Creating an optimized production build...
Failed to compile.

Failed to minify the code from this file: 

 	./node_modules/json-rpc-engine/src/index.js:5 

Read more here: http://bit.ly/2tRViJ9

which says :

Some third-party packages don't compile their code to ES5 before publishing to npm. This often causes problems in the ecosystem because neither browsers (except for most modern versions) nor some tools currently support all ES6 features. We recommend to publish code on npm as ES5 at least for a few more years.

It would be nice to publish a ES5 compiled version of json-rpc-engine (issue related in metamask/mascara)

Many thanks!

Incorrect error code for undefined method

Originally posted by @Qqwy at MetaMask/metamask-extension#4693:


Expected Behaviour

The call

web3.currentProvider.sendAsync({id: 1, method: "does_not_exist", params: []}, console.log)

returns

{
  "id": 1,
  "error": {
    "code": -32601,
    "message": "JSON-RPC method not found"
  }
}

(obviously, the actual content string of the message field is not specified by the standard, but something akin to this would probably be the most understandable)

Actual Behaviour

This call returns

{
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal JSON-RPC error."
  }
}

This means that MetaMask (or possibly one of its dependencies) does not properly follow the JSON-RPC Spec.

Browser+OS used

This is using MetaMask version 4.8.0 on FireFox on Manjaro Linux, but I doubt this problem is stack-specific.

NPM releases

It seems that npm releases aren't generating a build. After a fresh npm install my directory (node_modules/json-rpc-engine) doesn't contain a build or lib as per the documentation.

node_modules/json-rpc-engine
├── CHANGELOG.md
├── README.md
├── package.json
├── src
│   ├── asMiddleware.js
│   ├── createAsyncMiddleware.js
│   ├── createScaffoldMiddleware.js
│   ├── getUniqueId.js
│   ├── idRemapMiddleware.js
│   ├── index.d.ts
│   ├── index.js
│   └── mergeMiddleware.js
└── test
    ├── asMiddleware.spec.js
    ├── basic.spec.js
    ├── createAsyncMiddleware.spec.js
    ├── idRemapMiddleware.spec.js
    └── mergeMiddleware.spec.js

Use `@metamask/utils` for types

@metamask/utils now houses most of the types from this package (JsonRpcRequest, JsonRpcResponse, and the like). The only thing that we haven't brought over yet is PendingJsonRpcResponse (this issue is tracked in MetaMask/utils#39). Once this is moved over, we can remove the types from this package and import them from @metamask/utils.

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because we are using your CI build statuses to figure out when to notify you about breaking changes.

Since we did not receive a CI status on the greenkeeper/initial branch, we assume that you still need to configure it.

If you have already set up a CI for this repository, you might need to check your configuration. Make sure it will run on all new branches. If you don’t want it to run on every branch, you can whitelist branches starting with greenkeeper/.

We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

Once you have installed CI on this repository, you’ll need to re-trigger Greenkeeper’s initial Pull Request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper integration’s white list on Github. You'll find this list on your repo or organiszation’s settings page, under Installed GitHub Apps.

Setting res.error in async middleware not work

async function getCode(req, res, next) {
    // do something
    await next();
    if (res && res.error) {
        res.error = null;
        res.result = "0x";
    }
  }

The upper middleware still can see the res.error object

Adding a LICENSE

I wanted to use this repository but I do not see a license. Can you please add a license file?

Post-migration cleanup

Tasks

  • Transfer open issues from the source repo into the core monorepo using the Transfer issue feature.
    • If applicable, rename to include package name to provide better context when encountered in the core monorepo.
  • For open PRs in the source repo, lock conversation (with no reason provided), and leave a comment requesting that authors reopen the PR in core with a link pointing to the discussion in the original PR.
This library has now been migrated into the [core monorepo](https://github.com/metamask/core/). This PR has been locked and this repo will be archived shortly. Going forward, releases of this library will only include changes made in the core repo.
- Please push this branch to core and open a new PR there.
- Optionally, add a link pointing to the discussion in this PR to provide context.
  • Leave a note in the source repo's README announcing the migration and pointing to core.
<table><tr><td><p align="center"><b>⚠️ PLEASE READ ⚠️</b></p><p align="center">This package has been migrated to our <a href="https://github.com/MetaMask/core"><code>core</code></a> monorepo, and this repository has been archived. Please note that all future development and feature releases will take place in the <a href="https://github.com/MetaMask/core"><code>core</code></a> repository.</p></td></tr></table>
  • Archive the source repo to prevent any changes from being pushed to it going forward.

References

Add promise-returning method

Maybe we just say "if no callback is provided to handle, return a promise".

Would there be any objection to this?

remove unused dependencies

"dependencies" currently contains "babel-preset-env" and "babelify"

afaik, they are used only during build, and thus can be moved into devDependency, and not clutter the client's tree.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.