Skip to content

Commit

Permalink
feat(http-protocol): Add reload method to http protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
Shane Osbourne authored and shakyShane committed Apr 7, 2015
1 parent ee2ba31 commit f6a3601
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 1 deletion.
4 changes: 4 additions & 0 deletions lib/async-tasks.js
Expand Up @@ -41,6 +41,10 @@ module.exports = [
step: "Starting the web-socket server",
fn: async.startSockets
},
{
step: "Adding the HTTP protocol",
fn: async.addHttpProtocol
},
{
step: "Starting the UI",
fn: async.startUi
Expand Down
22 changes: 22 additions & 0 deletions lib/async.js
Expand Up @@ -228,6 +228,28 @@ module.exports = {
}
});
},
/**
* @param bs
* @param done
*/
addHttpProtocol: function (bs, done) {

if (!bs.options.get("httpProtocol")) {
return done(null);
}

/**
* Add a middleware to listen to http
* requests in the BrowserSync http protocol namespace
*/
bs.addMiddleware(
bs.options.getIn(["httpProtocol", "path"]),
require("./http-protocol").middleware(bs),
{override: true}
);

done();
},
/**
*
* @param {BrowserSync} bs
Expand Down
10 changes: 10 additions & 0 deletions lib/default-config.js
Expand Up @@ -339,6 +339,16 @@ module.exports = {
}
},

/**
* @property httpProtocol
* @param {String} [path="/__browser_sync__"]
* @since 2.6.0
* @type Object
*/
httpProtocol: {
path: "/__browser_sync__"
},

/**
* A map of file-extensions -> dom element.
* Useful if you're serving files with unusual file extensions
Expand Down
59 changes: 59 additions & 0 deletions lib/http-protocol.js
@@ -0,0 +1,59 @@
"use strict";

var queryString = require("query-string");
var proto = exports;

/**
* Use BrowserSync options + querystring to create a
* full HTTP/HTTTPS url.
*
* Eg. http://localhost:3000/__browser_sync__?method=reload
* Eg. http://localhost:3000/__browser_sync__?method=reload&args=core.css
* Eg. http://localhost:3000/__browser_sync__?method=reload&args=core.css&args=core.min
*
* @param args
* @param bs
* @returns {string}
*/
proto.getUrl = function (args, bs) {
return [
bs.options.getIn(["urls", "local"]),
bs.options.getIn(["httpProtocol", "path"]),
"?",
queryString.stringify(args)
].join("");
};

/**
* Return a middleware for handling the requests
* @param {BrowserSync} bs
* @returns {Function}
*/
proto.middleware = function (bs) {

return function (req, res) {

var params = queryString.parse(req.url.replace(/^.*\?/, ""));

if (!params) {
return;
}

if (require.resolve("./public/" + params.method)) {

require("./public/" + params.method)(bs.events).apply(null, [params.args]);

var output = [
"Called public API method `.%s()`".replace("%s", params.method),
"With args: " + JSON.stringify(params.args)
];

res.end(output.join("\n"));

} else {
res.end("Public API method `" + params.method + "` not found.");
}


};
};
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -50,6 +50,7 @@
"meow": "^3.1.0",
"opn": "^1.0.0",
"portscanner": "^1.0.0",
"query-string": "^1.0.0",
"resp-modifier": "^2.0.1",
"serve-index": "^1.6.3",
"serve-static": "^1.9.1",
Expand All @@ -75,7 +76,7 @@
"istanbul-coveralls": "^1.0.0",
"mocha": "*",
"q": "^1.1.2",
"request": "^2.51.0",
"request": "^2.55.0",
"sinon": "^1.12.1",
"slugify": "^0.1.0",
"socket.io-client": "^1.3.5",
Expand Down
72 changes: 72 additions & 0 deletions test/specs/http-protocol/http.reload.js
@@ -0,0 +1,72 @@
"use strict";

var browserSync = require("../../../index");
var request = require("request");
var assert = require("chai").assert;
var sinon = require("sinon");
var proto = require("../../../lib/http-protocol");

describe("HTTP protocol", function () {

var bs, spy;

before(function (done) {

browserSync.reset();

var config = {
server: "test/fixtures",
logLevel: "info",
open: false,
online: false
};

bs = browserSync.init(config, done).instance;

spy = sinon.spy(bs.events, "emit");
});

afterEach(function () {
spy.reset();
});

after(function () {
bs.cleanup();
});

it("responds to reload event with no args", function (done) {

var url = proto.getUrl({method: "reload"}, bs);

request(url, function (e, r, body) {
sinon.assert.calledWith(spy, "browser:reload");
assert.include(body, "Called public API method `.reload()`");
assert.include(body, "With args: undefined");
done();
});
});
it("responds to reload event with multi file paths", function (done) {

var url = proto.getUrl({method: "reload", args: ["core.min.css", "core.css"]}, bs);

request(url, function (e, r, body) {
sinon.assert.calledWith(spy, "file:changed");
sinon.assert.calledWithExactly(spy, "file:changed", { path: "core.min.css", log: true, namespace: "core" });
assert.include(body, "Called public API method `.reload()`");
assert.include(body, "With args: [\"core.min.css\",\"core.css\"]");
done();
});
});
it("responds to reload event with single file path", function (done) {

var url = proto.getUrl({method: "reload", args: "somefile.php"}, bs);

request(url, function (e, r, body) {
sinon.assert.calledWith(spy, "file:changed");
sinon.assert.calledWithExactly(spy, "file:changed", { path: "somefile.php", log: true, namespace: "core" });
assert.include(body, "Called public API method `.reload()`");
assert.include(body, "With args: \"somefile.php\"");
done();
});
});
});

0 comments on commit f6a3601

Please sign in to comment.