
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
A simple ajax library (using XMLHttpRequest) that returns flyd streams.
Many of the options, terminology, and response objects are directly from the normal XMLHttpRequest API. See the MDN Articles on that topic for details around how to work with response and progress objects.
Example GET request
// Calling request(...) immediately makes the request
const response = request({
method: 'GET'
, url: 'http://spacejam.com'
, path: '/'
, query: 'x=y' // data to send; must be text, FormData, or an object (objects get JSON.stringify-ed)
, headers: {'Content-Type': 'application/json'} // any number of header key/vals
, withCredentials: true // whether to send cookies
})
// The response object has four keys: .load, .error, .progress, and .abort
// Each of these keys holds a stream of request objects for the corresponding event
// Most of the time you will just use .load stream
const resp$ = request.load // flyd stream of request objects when the response is loaded
flyd.map(r => console.log('Response!', r.body, r.status), resp$)
Example POST request
request({
method: 'post'
, path: '/users'
, send: {name: 'Finn Mertens', email: 'finn@ooo.com'} // Can be an Object, String, or FormData
})
// If you leave out url, it will post to the path on the current domain
// If you pass in Object into the .send property, it will convert it to a JSON string by default
The request function immediately returns an object with a set of streams:
// object that gets returned by the request function:
{
load // stream of a request object when the request is completed
, error // stream of event object when the request cannot be completed due to some error
, progress // stream of event object on progress events in the request
, abort // stream of event object on aborted request event
}
Most of the time you will only need the .load stream -- error and progress are useful for file transfers.
Each of the above streams will emit the exact corresponding event or request objects as described here: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
The .load stream will have a .body property, which will contain a parsed JS object of JSON data, if the response's had 'json' in its content type. Otherwise it will be a String.
You can map over any of these streams to work with the responses and events. Example usage:
let getPosts = request({ method: 'GET' , path: '/posts' })
flyd.map(req => console.log('Completed request!', req.body), getPosts.load)
flyd.map(ev => console.log('Error event!', ev), getPosts.error)
flyd.map(ev => console.log('Progress event!', ev), getPosts.progress)
One easy way to pre-configure ajax requests is to simply define your own module that wraps the request function.
import request from 'flyd-ajax'
import R from 'ramda'
import flyd from 'flyd'
const apiRequest = (method, path, data) =>
request({
method
, path
, url: api_url
, send: data
, headers: {'Content-Type': 'application/json', 'X-CSRF-Token': 'xyz'}
}).load
// Stream of post responses, could be failure or success
const response$ = apiRequest('post', '/users' {name: 'Finn Mertens'})
// Stream of user data
const createdUser$ = R.compose(
flyd.map(r => r.body)
, flyd.filter(R.propEq('status', 200))
)(response$)
// Stream of error messages from creating a user
const errorMessage$ = R.compose(
flyd.map(r => r.body.error)
, flyd.filter(r => r.status !== 200)
)(response$)
Tests use zuul and assert
npm run test
Develop the .es6 files and transpile them to .js with:
npm run build
flyd-ajax comes with a built-in utility for mocking ajax requests for frontend unit testing. The require path is flyd-ajax/mock
Example:
import assert from 'assert'
import request from 'flyd-ajax'
import mockRequest from 'flyd-ajax/mock'
suite('test an ajax call')
test('it handles some ajax', () => {
mockRequest.setup() // This overwrites XMLHttpRequest
const status = 201
body = 'hi'
mockRequest.handle('get', 'http://localhost:420/test', {status, body}) // mock a response from the server for a specific endpoint
// Make the request as you normally would
const resp = request({method: 'get', url: 'http://localhost:420', path: '/test'})
// The request will be made synchronously and the response is immediately available
assert.deepEqual(resp.load().body, {status, body})
// Restore XMLHttpRequest
mock.teardown()
})
Mock API:
setup() -- Overwrite window.XMLHttpRequestteardown() -- Restore window.XMLHttpRequesthandle(method, url, responseObject) -- Catch and handle requests to this endpointThe responseObject can have these properties:
body -- mock response bodyheaders -- mock response headersstatus -- mock response status codeFAQs
Functional reactive ajax client
We found that flyd-ajax 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.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.