Skip to content

Commit

Permalink
Merge pull request #32 from hdgarrood/node-support
Browse files Browse the repository at this point in the history
node.js support, via npm package 'xmlhttprequest'
  • Loading branch information
garyb committed Aug 5, 2015
2 parents 58d9282 + 13d196f commit 1f5db76
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 15 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ install:
- npm install && bower install
script:
- gulp
- node ./test-server.js &
- node tmp/test.js
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"gulp-plumber": "^1.0.0",
"gulp-purescript": "^0.5.0",
"express": "^4.13.1",
"body-parser": "^1.13.2"
"body-parser": "^1.13.2",
"xmlhttprequest": "^1.7.0"
}
}
46 changes: 42 additions & 4 deletions src/Network/HTTP/Affjax.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,52 @@
/* jshint browser: true */
/* global exports */
/* global XMLHttpRequest */
/* global require */
/* global module */
"use strict";

// module Network.HTTP.Affjax

// jshint maxparams: 5
exports._ajax = function (mkHeader, options, canceler, errback, callback) {
var platformSpecific = { };
if (typeof module !== "undefined" && module.exports) {
// We are on node.js
platformSpecific.newXHR = function () {
var XHR = require("xmlhttprequest").XMLHttpRequest;
return new XHR();
};

platformSpecific.fixupUrl = function (url) {
var urllib = require("url");
var u = urllib.parse(url);
u.protocol = u.protocol || "http:";
u.hostname = u.hostname || "localhost";
return urllib.format(u);
};

platformSpecific.getResponse = function (xhr) {
// the node package 'xmlhttprequest' does not support xhr.response.
return xhr.responseText;
};
} else {
// We are in the browser
platformSpecific.newXHR = function () {
return new XMLHttpRequest();
};

platformSpecific.fixupUrl = function (url) {
return url || "/";
};

platformSpecific.getResponse = function (xhr) {
return xhr.response;
};
}

return function () {
var xhr = new XMLHttpRequest();
xhr.open(options.method || "GET", options.url || "/", true, options.username, options.password);
var xhr = platformSpecific.newXHR();
var fixedUrl = platformSpecific.fixupUrl(options.url);
xhr.open(options.method || "GET", fixedUrl, true, options.username, options.password);
if (options.headers) {
for (var i = 0, header; (header = options.headers[i]) != null; i++) {
xhr.setRequestHeader(header.field, header.value);
Expand All @@ -28,7 +66,7 @@ exports._ajax = function (mkHeader, options, canceler, errback, callback) {
var i = header.indexOf(":");
return mkHeader(header.substring(0, i))(header.substring(i + 2));
}),
response: xhr.response
response: platformSpecific.getResponse(xhr)
})();
};
xhr.responseType = options.responseType;
Expand Down
26 changes: 16 additions & 10 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -55,41 +55,47 @@ assertEq x y = if x == y
typeIs :: forall e a. a -> Assert e Unit
typeIs = const (return unit)

main = runAff throwException (const $ log "affjax: All good!") $ do
main = runAff (\e -> print e >>= \_ -> throwException e) (const $ log "affjax: All good!") $ do
let ok200 = StatusCode 200
let notFound404 = StatusCode 404

A.log "GET /does-not-exists: should be 404 Not found after retries"
(attempt $ retry (Just 5000) affjax $ defaultRequest { url = "/does-not-exist" }) >>= assertRight >>= \res -> do
-- A complete URL is necessary for tests to work on Node.js
let prefix = append "http://localhost:3838"
let mirror = prefix "/mirror"
let doesNotExist = prefix "/does-not-exist"
let notJson = prefix "/not-json"

A.log "GET /does-not-exist: should be 404 Not found after retries"
(attempt $ retry (Just 5000) affjax $ defaultRequest { url = doesNotExist }) >>= assertRight >>= \res -> do
typeIs (res :: AffjaxResponse String)
assertEq notFound404 res.status

A.log "GET /mirror: should be 200 OK"
(attempt $ affjax $ defaultRequest { url = "/mirror" }) >>= assertRight >>= \res -> do
(attempt $ affjax $ defaultRequest { url = mirror }) >>= assertRight >>= \res -> do
typeIs (res :: AffjaxResponse Foreign)
assertEq ok200 res.status

A.log "GET /does-not-exist: should be 404 Not found"
(attempt $ affjax $ defaultRequest { url = "/does-not-exist" }) >>= assertRight >>= \res -> do
(attempt $ affjax $ defaultRequest { url = doesNotExist }) >>= assertRight >>= \res -> do
typeIs (res :: AffjaxResponse String)
assertEq notFound404 res.status

A.log "GET /not-json: invalid JSON with Foreign response should throw an error"
assertLeft =<< attempt (get "/not-json" :: Affjax _ Foreign)
assertLeft =<< attempt (get doesNotExist :: Affjax _ Foreign)

A.log "GET /not-json: invalid JSON with String response should be ok"
(attempt $ get "/not-json") >>= assertRight >>= \res -> do
(attempt $ get notJson) >>= assertRight >>= \res -> do
typeIs (res :: AffjaxResponse String)
assertEq ok200 res.status

A.log "POST /mirror: should use the POST method"
(attempt $ post "/mirror" "test") >>= assertRight >>= \res -> do
(attempt $ post mirror "test") >>= assertRight >>= \res -> do
assertEq ok200 res.status
assertEq "POST" (_.method $ unsafeFromForeign res.response)

A.log "PUT with a request body"
let content = "the quick brown fox jumps over the lazy dog"
(attempt $ put "/mirror" content) >>= assertRight >>= \res -> do
(attempt $ put mirror content) >>= assertRight >>= \res -> do
typeIs (res :: AffjaxResponse Foreign)
assertEq ok200 res.status
let mirroredReq = unsafeFromForeign res.response
Expand All @@ -103,6 +109,6 @@ main = runAff throwException (const $ log "affjax: All good!") $ do
-- assertEq (Just "test=test") (lookupHeader "Set-Cookie" res.headers)

A.log "Testing cancellation"
canceler <- forkAff (post_ "/mirror" "do it now")
canceler <- forkAff (post_ mirror "do it now")
canceled <- canceler `cancel` error "Pull the cord!"
assertMsg "Should have been canceled" canceled

0 comments on commit 1f5db76

Please sign in to comment.