Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
consumer-contracts
Advanced tools
Consumer-driven contracts in JavaScript
Consumer-driven contracts let you move fast without breaking things.
API consumers codify their expections of your service in an executable contract. This defines the type of response that they expect for a given request. Contracts give you an insight into which parts of your API clients depend on, and which parts can be changed without fear of breaking them.
This project lets you write executable contracts in JavaScript. It uses request to make HTTP requests and Joi to validate API responses. Contracts are defined as JavaScript modules in a contracts
directory at the root of your project and can be executed using the consumer-contracts
tool.
Install the consumer-contracts
tool globally:
npm install --global consumer-contracts
Install the consumer-contracts
module locally (this gives you access to the contract defintion interface in your contract files):
npm install --save consumer-contracts
Create a contracts
directory at the root of your project:
mkdir contracts
Create a JavaScript file within the contracts
directory for your first contract. The example below is a contract for the GitHub User API, we'll call it user-api.js
. In this example, the consumer depends on the login
, name
and public_repos
properties returned in the response body.
var Contract = require('consumer-contracts').Contract;
var Joi = require('consumer-contracts').Joi;
module.exports = new Contract({
name: 'User API',
consumer: 'My GitHub Service',
request: {
method: 'GET',
url: 'https://api.github.com/users/robinjmurphy'
},
response: {
statusCode: 200,
body: Joi.object().keys({
login: Joi.string(),
name: Joi.string(),
public_repos: Joi.number().integer()
})
}
});
To validate the contract, run the following command at the root of your project directory:
consumer-contracts run
You should see that the contract validates:
✓ My GitHub Service – User API
1 passing
Each contract contains four properties; consumer
, name
, request
and response
.
var Contract = require('consumer-contracts').Contract;
var Joi = require('consumer-contracts').Joi;
module.exports = new Contract({
name: 'Contract name',
consumer: 'Consumer name',
request: {
// ...
},
response: {
// ...
}
});
consumer
The consumer
property appears in the output of the consumer-contracts
tool and should be the name of the consuming service that the contract applies to.
name
The name
property appears in the output of the consumer-contracts
tool and helps you identfiy each individual contract.
request
The request
property defines the HTTP request that the contract applies to. All of the options supported by request are valid. This means you can specify headers and SSL configuration options (among other things) for a given request:
request: {
method: 'GET',
url: 'https://exmaple.com/users/fred',
headers: {
Accept: 'text/xml'
},
cert: fs.readFileSync('/path/to/my/cert.crt'),
key: fs.readFileSync('/path/to/my/cert.key')
}
response
The response
object validates the response returned by your service. The entire object is treated as a Joi schema that validates the res
object returned by request
. This means that the response's status code, headers and JSON body can all be validated using Joi's flexible schema language. The following options are passed to Joi's validate()
function:
{
allowUnknown: true,
presence: 'required'
}
This means that any fields you choose to validate are required by default. To indicate that a field is optional, use the optional()
modifier.
To require a specific HTTP status code, set the statusCode
property to that value:
response: {
statusCode: 200
}
To allow a range of different status codes, you can use Joi's valid()
function:
response: {
statusCode: Joi.any().valid(200, 201, 202)
}
The response headers can be validated using a Joi schema:
response: {
headers: Joi.object().keys({
'Location': Joi.string().regex(/\/users\/\d+/),
'Content-Type': 'application/json'
})
}
The response body can be validated using a Joi schema:
response: {
body: Joi.object().keys({
name: Joi.string(),
items: Joi.array().items(Joi.object().keys({
id: Joi.number.integer()
}))
})
}
client
optionalYou can use a pre-configured request client for your contracts using the client
property. This can be useful when you have a set of common request options across contracts.
var Contract = require('consumer-contracts').Contract;
var Joi = require('consumer-contracts').Joi;
var client = require('request').defaults({
headers: {
authorization: 'Bearer xxx'
}
});
module.exports = new Contract({
name: 'Contract name',
consumer: 'Consumer name',
request: {
// ...
},
response: {
// ...
},
client: client
});
run
To validate all of the contracts in the contracts
directory, type:
consumer-contracts run
This works recursively, which means you can keep the contracts for each of your consumers in a separate subdirectory.
To run a single contract, pass a filename to the run
command:
consumer-contracts run ./contracts/consumer-a/contract-1.js
FAQs
Consumer driven contracts for Node.js
We found that consumer-contracts demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.