npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

chapar

v1.1.3

Published

Reliable Express/Node.js RPC over RabbitMQ

Downloads

70

Readme

Chapar**

Reliable Express/Node.js RPC over RabbitMQ

** Chapar Khaneh, is a Persian term for the postal service used during the Achaemenid era. The system was created by Cyrus the Great, the founder of the Persian Empire, as the royal method of communication throughout the empire. Each "Chapar Khaneh" was a station mainly located along the Royal Road, a 2500 km ancient highway, connecting most of the major cities of the empire. https://en.wikipedia.org/wiki/Chapar_Khaneh

Micro-service design can solve lots of development problems, yet a lightweight reliable and robust communication system is needed.

Why Chapar?

| | Pros | Cons | | ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | HTTP | Main web frameworks such as Express use this protocol. Every one is familiar with express. | HTTP 1.1 has lots of overhead in memory and connection usage. | | Publish/Subscribe | Publish/Subscribe protocols are well-suited for high throughput data pipeline as they provide a lightweight communication layer. | Programmers have to change their code layout to use pub/sub. Specially they cannot use Express framework. |

Chapar helps you to use AMQP as underlying communication protocol with absolutely zero changes while coding Express/Node.js.

How it works?

Suppose you have two micro-services in your production server, MS1 and MS2. MS1 has very high number of requests per seconds that needs to be processed by MS2. MS2 is a server for MS1.

You use Chapar.RPCServer middleware in MS2 and Chapar.RPCClient in MS1. In MS1 you call an Express route of MS2. Chapar.RPCClient creates a message with shape of actual HTTP request and sends it with AMQP with RabbitMQ broker.

This message pushes Chapar.RPCServer in MS2. MS2 calls the internal controller (only function call, no TCP handshake, no HTTP overhead), gets the result and sends the response back on a response queue. You just need to await for Chapar.RPCClient to provide you the response.

Install

npm i -s chapar

Server Usage

Express app.js:

import express from 'express';
import { RPCServer } from 'chapar';

const app = express();

app.use('/', indexRouter);
// Other Express middlewares

const config = {
  rabbitMQ: { // required
    host: 'localhost', // required
    port: 5672, // required
    username: 'RABBITMQ_UESRNAME', // optional, (needed if rabbitMQ requires authentication)
    password: 'RABBITMQ_PASSWORD' // optional, (needed if rabbitMQ requires authentication)
  },
  exchange: { // required
    name: 'MY_APP_EXCHANGE_NAME', // required
    type: 'direct', // optional, default='direct'
    options: { // optional
      durable: true // optional, default='{ durable: true }'
    }
  },
  requestQueue: { // optional
    name: 'HTTP_OVER_AMQP', // optional, default='HTTP_OVER_AMQP'
    options: { // optional
      exclusive: false // optional, default={ exclusive: false }
    },
    bindKey: 'HTTP_OVER_AMQP_ROUTING_KEY', // optional default='HTTP_OVER_AMQP_ROUTING_KEY',
    prefetch: 0 // optional, default=0 which means unlimited
  }
};

RPCServer(app, config);

// Common Express error handler

module.exports = app;

And thats it. no need to other changes to be done in your Express server application.

Client Usage

configure an export an instance of Chapar.RPCClient:

import {RPCClient} from 'chapar';

const ConfiguredRPCClient = await RPCClient({
  rabbitMQ: { // required
    host: 'localhost', // required
    port: 5672, // required
    username: 'RABBITMQ_USERNAME', // optional, (needed if rabbitMQ requires authentication)
    password: 'RABBITMQ_PASSWORD' // optional, (needed if rabbitMQ requires authentication)
  },
  exchange: { // required
    name: 'MY_APP_EXCHANGE_NAME', // required
    type: 'direct', // optional, default='direct'
    options: { // optional
      durable: true // optional, default='{ durable: true }'
    }
  },
  replyQueue: {
    name: '', // optional, default=''
    options: { // optional
      exclusive: true // optional, default={ exclusive: true }
    },
    prefetch: 0 // optional, default=0 which means unlimited
  },
  publish: { // optional
    routingKey: 'HTTP_OVER_AMQP_ROUTING_KEY', // optional, default='HTTP_OVER_AMQP_ROUTING_KEY',
    options: { // optional
      persistent: true // optional, default=true
    }
  },
  // optional
  queryStringStringifier: {
    extended: true, // default=true, if true chapar uses 'qs' library to stringify query object in requests
    // o.w. it uses 'querystring' library
    options: {} // options passed to chosen query string stringifier library
  }
});

Some piece of code that need some processing in remote micro-server.

Access to remote micro-server with just one line of code:

const { status, body, headers } = await ConfiguredRPCClient(
    'GET', // method
    '/users', // url
    {}, // cookies 
    { name: 'John' }, // query
    { Authorization: 'Bearer abcd...' }, // headers
    {} // body
);
console.log(`status: ${status}, body: ${body}, headers: ${headers}`);

An Example output may be:

status: 200,
body: { name: 'John', lastname: 'Doe', phone: '+1001001001' },
headers: { 'x-last-login': '1583048837564' }

Mutual Server-Client Usage

In some cases, both micro-services may act as client and both as server. i.e. each serves some processing to for the other. You can use both Chapar.RPCServer and Chapar.RPCClient in each one the micro-services.

Query String Functionality Support

From version 1.1.0 Chapar started to support requests which may contain complex query string objects. You can configure chapar.RPCClient to stringify your query object with qs or querystring npm libraries through config.queryStringStringifier.extended.

This parameter should be set according to your remote express application. If your server express app can support extended query string parser i.e. app.use(express.urlencoded({ extended: true })); is set in your express server app , you can take advantage of complex query string objects in your client by setting config.queryStringStringifier.extended: true. If your server uses app.use(express.urlencoded({ extended: false })); client should be configured with config.queryStringStringifier.extended: false. For more information about how does express deals with query strings by default, refer to express urlencoded api.

NOTE: Chapar.RPCServer automatically reads main express application and uses the the main application query parser. No need to set any thing in Chapar.RPCServer.

Changelog

  • Version 1.1.2 fixed a bug in http headers validation.
  • Version 1.1.1 export chapar in both default and explicit way so that both import chapar from 'chapar' and import {RPCServer} from 'chapar' works.
  • Version 1.1.0 support for complex query string objects.
  • From 1.0.0 to 1.0.13 first public release, debug and bug fixes, some changes are backward UNcompatible

Test

run server example:

npm run dev-run-example-rpc-express

run client example:

npm run dev-run-example-rpc-client

run tests:

npm run test