Security News
Input Validation Vulnerabilities Dominate MITRE's 2024 CWE Top 25 List
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
"There ain't no getting offa this train we on!"
Highwind provides a simple, fast, configurable Express server that makes it easy to simulate API responses from your production server.
Highwind will automatically pull down production data from the URL you specify and save it locally when it cannot find a fixture for the requested URL. This allows for painless feature testing, with immediately-generated response data that highly approximates your production API responses.
Highwind also comes with a bevy of configuration options that make it dead simple to specify unique response statuses and headers, dynamically mix fixture data with request body params, serve concurrently from multiple ports, and avoid redundant response caching.
Highwind provides a slim API that makes it easy to drop into a test suite or task runner:
import highwind from 'highwind';
const options = {
prodRootURL: 'http://www.refinery29.com/',
fixturesPath: `${__dirname}/fixtures`
};
// booting your server
highwind.start(options, (err, result) => {
// 'result.app' is the express object
//
// 'result.servers' represents all currently running Highwind servers,
// and is an array of server objects with signature:
// {
// port : number
// server : instance of the express object in 'result.app'
// active : bool
// }
//
// The important thing to note is that by the time the callback is called,
// result[n].server is currently listening for requests.
});
// closing your server
// first argument is an optional array of servers with the same signature
// as highwind.start's `result.servers`. If this param is not passed in,
// highwind.close will close all currently running servers.
highwind.close(null, (err) => {
// do something after all currently running servers have been closed
});
Highwind only needs to know your the root URL for your production API and the absolute path to your fixtures directory to get started.
By default, Highwind listens for requests on port 4567. You can change that in the config, however.
You may supply your fixtures as JSON, JS, or HTML files:
Filepath: ./fixtures/myApiResponse.json
{
"result": {
"foo": "bar"
}
}
In this example, requesting localhost:4567/myApiResponse
would return the above JSON.
Filepath: ./fixtures/myApiResponse.html
<html>
<head>
<title>Test</title>
</head>
<body>
</body>
</html>
In this example, requesting localhost:4567/myApiResponse
would return the above HTML.
Filepath: ./fixtures/myApiResponse.js
export default () => {
return {
result: {
foo: "bar"
}
};
}
In this example, requesting localhost:4567/myApiResponse
would return the following JSON.
{
"result": {
"foo": "bar"
}
}
These are dropped in to the options object passed to highwind.start()
during instantiation.
prodRootURL
(string, required):
fixturesPath
: (string, required):
corsWhitelist
(array of string):
overrides
(object):
app
object (get
, post
, put
, delete
, all
). Examples follow below.queryStringIgnore
(array of RegExp):
[]
/\?analytics=[^\&]+/
would result in a query for /homepage
and /homepage?analytics=true
saving and searching for the same local response fixture.ports
(array of number):
[4567]
encoding
(string):
'utf8'
.fs
for reading/writing local responses.quiet
: (boolean)
false
.saveFixtures
: (boolean)
true
.latency
: (number)
In some instances you may want to override the behavior for a specific route.
Here are some examples of HTTP route overrides and their use cases.
import loginFixture from './fixtures/login.json';
...
overrides: {
post: [
{
route: '/api/login',
response: loginFixture,
status: 503
}
]
}
This configures the mock API to respond to POST requests to '/api/login'
with the fixture object assigned to response
and a 503
status.
import emailSignupFixture from './fixtures/email_signup.json';
...
overrides: {
post: [
{
route: '/api/sign_up',
response: emailSignupFixture,
mergeParams(response, params) {
return Object.assign({}, response, { result: params });
}
}
]
}
Just as in the previous example, this will result in POST requests to '/api/sign_up'
being served the fixture assigned to response
. The distinction here is the mergeParams
callback. This intercepts the POST params bound to Express's res.body
and assigns them to the result
key of the response object (emailSignupFixture
in this example).
get: [
{
route: '/legacy_route',
headers: {
'Content-Type': 'text/html'
}
}
]
This configures the mock API to respond to get
requests for /legacy_route
with a non-JSON 'Content-Type'
header. This also prevents the mock API from attempting to handle data served from the local legacy_route
fixture as JSON. Since no response
object is specified, our mock API will default to serving a fixture from ${fixturesPath}/legacy_route.json
.
N.B.: Under the hood, the headers
object is passed to Express's response.set()
method. That means you can specify any HTTP header key/value pairs you'd like here, not just 'Content-Type'
.
overrides: {
get: [
{
route: '/api/search',
withQueryParams: { query: 'foo' },
response: {
keyword: 'foo',
result_count: 15
},
status: 200
}
]
}
This serves the specified response only when the query string matches the params specified in the withQueryParams
object; in all other cases, it defers to the default response.
Highwind recognizes when a fixture file ends in .js
instead of .json
. When this is the case, Highwind evaluates the export default
function of that file and attempts to return its output as JSON.
This can be useful for creating many fixtures based off of a few base fixtures without the hassle of copying and maintaining 100s of lines of identical JSON in each fixture file.
export default () => {
// Import a complex JSON fixture as a JS object
const baseJSON = JSON.parse(fs.readFileSync('./fixtures/persisted_json_route.json'));
// Modify a few values
baseJSON.title = "I am overriding the title value";
// Return the modified JS object back to Highwind for parsing back into JSON
return baseJSON;
}
Highwind serves all routes with callback
specified in the query string as
JSONP, not JSON, by default.
You can disable this by specifying a non-JS 'Content-Type'
header in an
override for a specific route or by adding something like
/callback\=([^\&]+)/
to your queryStringIgnore
collection.
MIT License © Refinery29, Inc. 2016-2018
FAQs
Mock API express server
We found that highwind demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 18 open source maintainers 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.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.