Security News
Supply Chain Attack Detected in Solana's web3.js Library
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Bluejax is a library that wraps jQuery's
ajax
function in Bluebird
promises. This is not the
first library of this kind, but the other libraries that existed when Bluejax
was created did not satisfy our needs, or appeared defunct.
Wraps jQuery.ajax
in Bluebird promises.
Optionally retry failed queries a number of times before giving up.
Optionally diagnoses failed queries: network failure, server down, something else?
In the 3.x and 2.x series: any version.
In the 1.x series: 1.11 or later. This being said, Bluejax probably works fine with 1.9 and 1.10.
Bluejax's is tested on Chrome, Firefox, IE11 and 10, Edge, Opera, and Safari (on El Capitan, Yosemite, Mavericks). We test against the latest versions offered by the vendors of these browsers on their respective platforms.
Bluejax's suite fails on IE9. I currently have no plans to work on adding support for IE9 but if you want to provide a pull request that will make Bluejax run on IE9 and will keep its current tests passing, you are welcome to do so.
Your loader should be configured so that it can find Bluejax, jQuery
and Bluebird. jQuery and Bluebird are requested by Bluejax as
jquery
and bluebird
respectively.
Once installed, you should just be able to do var bluejax = require("bluejax")
. jQuery and Bluebird should also be installed. Just like in
the AMD case, they are required as jquery
and bluebird
respectively.
script
elementsIf you are just loading it in a browser with script
. jQuery and
Bluebird must have been loaded beforehand.
The module exports these items:
ajax(...)
is a function that passes all its arguments to
jQuery.ajax
. By default, it returns a promise that resolves to the data
received. If it fails, it will reject the promise with a GeneralAjaxError
or a an exception whose class is derived from GeneralAjaxError
.
ajax(url).then(function (data) {
document.getElementById("foo").innerHTML = data;
});
ajax$(...)
does the same thing as ajax(...)
but it returns an object
that has the keys xhr
and promise
. The value of promise
is the
same as the value returned by ajax(...)
the xhr
object is an object
like the jqXHR
returned by jQuery.ajax
.
Important note: the xhr
object only encapsulate the tries that
Bluejax performs. It will be successful if the Ajax query was successful
within the number of tries specified and will fail if the tries failed. It is
not affected by the diagnosis done after all tries failed. If you need
diagnostic information you must use the promise.
This call can be useful for the purpose of inserting Bluejax in contexts that
expect to work with jQuery.ajax
. For instance, I can make Backbone use
Bluejax for all its Ajax requests. In this case, I use a special
useBluejax
option to turn on the use of Bluejax. Those calls that do use
use useBluejax
go through unchanged.
var origAjax = Backbone.ajax;
Backbone.ajax = function ajaxWrapper(options) {
if (!options.useBluejax) {
return origAjax.call(this, options);
}
// Return the xhr because this is what callers to ``Backbone.ajax``
// expect.
return ajax$(options).xhr;
};
Although the callers of Backbone.ajax
do not get a promise. The callers
still benefit from the possibility of retrying queries. If everything goes to
hell they do not get the diagnosis information themselves but a handler that
listens for unhandled rejections could use the rejection information to
provide an informative error message. This is actually the case for my
Backbone application that uses the snippet above.
make(options, field)
is a utility function that creates a new
ajax$
-like function. The options
parameter is an object containing
Bluejax options. The returned value is a new function that works like ajax
but which has its Bluejax options set to the values contained in the
options
object.
The field
parameter allows you to automatically extract a field. If you do
not specify a value for field
, then the return value will be the same
object returned by $ajax
. If you want to retrieve only one field from that
object, you must specify the field name. To get the same value as the
ajax(...)
call, you'd need to put "promise"
for the value of
field
.
Example: it is possible to create a new function that will return verbose
results: var ajaxVerbose = make({verboseResults: true}, "promise");
and
use it in the same way ajax
is used:
ajaxVerbose("http://example.com").spread(function (data, textStatus,
jqXHR) {
...
});
GeneralAjaxError
is a class that derives from JavaScript's stock
Error
. It aims to provide a somewhat saner way to handle Ajax errors than
what jQuery provides by default. When jQuery.ajax
fails, Bluejax creates
an exception derived from GeneralAjaxError
that has its jqXHR
,
textStatus
and errorThrown
fields set to the corresponding fields of
callback that should be passed to the .fail(...)
method of the object
returned by jQuery.ajax
. Its message
field is constructed as follows:
If errorThrown
is set, the message is "Ajax operation
failed: errorThrown
(jqXHR.status
).".
Otherwise, if textStatus
is set, the message is "Ajax
operation failed: textStatus
.".
Otherwise, the message is "Ajax operation failed."
HttpError
is raised if the response had an HTTP status that signaled an
error.
TimeoutError
is raised if the rejection was caused by a timeout.
AbortError
is raised if the rejection was caused by an abort.
ParserError
is raised if the rejection was caused by a parsing problem.
ConnectivityError
indicates a network problem. This class of error is
never raised directly but is raised through its children:
BrowserOfflineError
is raised if the browser is offline.
ServerDownError
is raised if the server is down.
NetworkDownError
is raised if the network is down.
If none of the more specialized cases above apply, then AjaxError
is
raised.
Bluejax currently supports these options:
tries
tells Bluejax to retry the query for a number of times. Note that
the value here should be a number greater than 1. (Values less than 1 yield
undefined behavior.)
shouldRetry
is a function with the following signature
shouldRetry(jqXHR, textStatus, errorThrown)
. It should return true
if
the query should be retried, or false
if an error should be returned
immediately.
If no value is specified, the default function returns true
if the
previous query failed due to reasons other than the HTTP status code
reporting an error, aborted or had a parser error. Basically, it retries the
connection if the issue appears to be at the network level rather than an
application issue.
delay
specifies the delay between retries, in milliseconds.
diagnose
is an object with the following keys:
on
must be true
for diagnosis to happen. (This makes diagnosis
easy to turn off, while keeping the other diagnosis settings intact.)
Make sure to read the section on diagnosis rules and URL transformations
below before to understand what it is that happens when you turn diagnosis
on!!!
serverURL
must be a URL that used to test whether your server is
running or not. We recommend making it a path that is inexpensive to
serve. For instance, your internet-facing nginx instance could have a rule
that serves 200 and no contents for GETs to /ping
. Bluejax uses this
URL to double check whether your server is up.
knownServers
must be an array of URLs to known internet
servers. Bluejax uses these URLs to determine whether the Internet is
accessible or not.
verboseExceptions
when set to true
will cause exception messages to
additionally contain the text "Called with: " followed by a JSON dump of the
options that were passed to ajax(...)
. This can be useful to identify
which call precisely is failing.
verboseResults
causes the promise to resolve to [data, textStatus, jqXHR]
where each element of the array is the corresponding parameter passed
to the callback of the .done(...)
method of the object returned by
jQuery.ajax
. You would use this in a case where just receiving data
is
not enough for your usage scenario.
Bluebird's .spread
method is useful to unpack the array:
ajax(url, {
bluejaxOptions: { verboseResults: true }
}).spread(function (data, textStatus, jqXHR) {...
There are two ways to set Bluejax options:
You can set set the bluejaxOptions
field on a settings object passed to
ajax
. Remember that ajax(...)
takes the same parameters as
jQuery.ajax
. When you pass a settings
parameter to the call, it may
contain a bluejaxOptions
field that sets verboseExceptions
:
bluejax.ajax({
url: "http://example.com",
bluejaxOptions: {
verboseExceptions: true
}
});
You can create a new ajax
-like function with make
.
Diagnosis happens only if the final try for the request failed with an error other than an HTTP error, an abort or a parser error. Otherwise, no diagnosis occurs and the error is reported immediately.
Bluejax uses the following rules when diagnosis is requested:
If navigator.onLine
is false, Bluejax reports that the browser is
offline.
If a serverURL
is specified, then it checks whether the server is
responds to a GET at this URL:
A. If the server responds, Bluejax reports the error that was reported by the last try.
B. If the server does not respond, Bluejax reports the result of a connectivity check.
serverURL
was not specified, Bluejax reports the result of a
connectivity check.If knownServers
does not exist or is an empty list, then it reports that
the server appears to be down.
Otherwise, Bluejax contacts all the servers. If none of them respond, then it reports that the network appears to be down. Otherwise, it reports that the server appears to be down.
For all URLs used in diagnosis, these two transformations are applied in order:
If the URL ends with a /
and has no query string, then the URL is
transformed by adding favicon.ico
. Requesting the root page of a site may
result in a large amount of data being returned. Requesting favicon.ico
would in most cases result in a relatively small amount of data.
If the URL has no query, then the URL is transformed by adding a query that is a single number corresponding to the current time. This is done to bust caches.
So if you specify a known server as http://www.google.com/
the URL used for
the query will be http://www.google.com/favicon.icon?ttttt
, where ttttt
is the number described above. If you specify http://www.example.com/foo
then the URL used for the query will be http://www.example.com/foo?ttttt
. If
the URL you give in the options contains a query, it won't be modified at
all. (We do not recommend such case.)
If you produce a pull request run gulp lint
and gulp test
first to make
sure they run clean. If you add features, do add tests.
We need a Mocha run to test loading Bluejax as a CommonJS module with script
elements. The Karma run, which exercises over 95% of the code, uses RequireJS
to load Bluejax.
Ideally, we combine the results of the Karma runs with the result of the Mocha
run. The problem though is that as we speak, karma-coverage
uses Istanbul
0.4.x but to get coverage with Mocha with code that has run through Babel, we
need Istanbul 1.0.0-alpha2 or higher. We've not been able to combine the formats
produced by the various versions.
Bluejax is tested using BrowserStack. BrowserStack provides this service for free under their program for supporting open-source software.
FAQs
jQuery AJAX wrapped in Bluebird promises.
We found that bluejax 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
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.