Skip to content

Commit

Permalink
Merge bf0e1e4 into 336afbc
Browse files Browse the repository at this point in the history
  • Loading branch information
jhnns committed Aug 3, 2014
2 parents 336afbc + bf0e1e4 commit aa4e46c
Show file tree
Hide file tree
Showing 22 changed files with 610 additions and 643 deletions.
49 changes: 14 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ phridge
========================================================================
**A bridge between [node](http://nodejs.org/) and [PhantomJS](http://phantomjs.org/).**

Working with PhantomJS in node is a bit cumbersome since you need to spawn a new PhantomJS process for every single task. However, spawning a new process is quite expensive (~1s) and thus can slow down your application significantly.
[![Build Status](https://travis-ci.org/peerigon/phridge.svg?branch=master)](https://travis-ci.org/peerigon/phridge)
[![Dependency Status](https://david-dm.org/peerigon/phridge.svg)](https://david-dm.org/peerigon/phridge)
[![Coverage Status](https://img.shields.io/coveralls/peerigon/phridge.svg)](https://coveralls.io/r/peerigon/phridge?branch=master)

Working with PhantomJS in node is a bit cumbersome since you need to spawn a new PhantomJS process for every single task. However, spawning a new process is quite expensive and thus can slow down your application significantly.

**phridge** provides an api to easily

Expand All @@ -13,7 +17,7 @@ Working with PhantomJS in node is a bit cumbersome since you need to spawn a new

Unlike other node-PhantomJS bridges **phridge** provides a way to run code directly inside PhantomJS instead of turning every call and assignment into an async operation.

**phridge** utilizes PhantomJS' built-in http server for [inter-process communication](http://en.wikipedia.org/wiki/Inter-process_communication). It stringifies the given function, sends it to PhantomJS and executes it there. Thus you can write your PhantomJS scripts inside your node modules in a clean and synchronous way.
**phridge** uses PhantomJS' stdin and stdout for [inter-process communication](http://en.wikipedia.org/wiki/Inter-process_communication). It stringifies the given function, passes it to PhantomJS via stdin, executes it in the PhantomJS environment and passes back the results via stdout. Thus you can write your PhantomJS scripts inside your node modules in a clean and synchronous way.

Instead of ...

Expand Down Expand Up @@ -71,19 +75,15 @@ phantom.run("h1", function (selector, resolve) {

Please note that the `phantom`-object provided by **phridge** is completely different to the `phantom`-object inside PhantomJS. So is the `page`-object. [Check out the api](#api-phantom) for further information.

Since communication via http is asynchronous **phridge** always returns promises. It uses [when.js](https://github.com/cujojs/when) which is Promises/A+ compliant, so using your favorite promise library should be no problem.
Since communication via stdin/stdout is always asynchronous **phridge** returns promises most of the time. It uses [when.js](https://github.com/cujojs/when) which is Promises/A+ compliant, so using your favorite promise library should be no problem.

<br />

Setup
Installation
------------------------------------------------------------------------

[![npm status](https://nodei.co/npm/phridge.png?downloads=true&stars=true)](https://npmjs.org/package/phridge)

[![Build Status](https://travis-ci.org/peerigon/phridge.svg?branch=master)](https://travis-ci.org/peerigon/phridge)
[![Dependency Status](https://david-dm.org/peerigon/phridge.svg)](https://david-dm.org/peerigon/phridge)
[![Coverage Status](https://img.shields.io/coveralls/peerigon/phridge.svg)](https://coveralls.io/r/peerigon/phridge?branch=master)

<br />

Examples
Expand Down Expand Up @@ -280,16 +280,7 @@ phridge.disposeAll().then(function () {
will terminate all processes.
**I strongly recommend to call** `phridge.disposeAll()` **when the node process exits as this is the only way to ensure that all child processes terminate as well.** Since `disposeAll()` is async it is not safe to call it on `process.on("exit")`. It is better to call it on `SIGINT` and `SIGTERM` or to hook into your regular exit flow.
<br />
<a name="a-note-on-security"></a>A note on security
------------------------------------------------------------------------
**phridge** spins up an http server inside PhantomJS which executes any JavaScript code it receives. Thus attackers could easily read the filesystem if the port is accessible for untrusted users. That's why **phridge** shares a secret with the child process which needs to be present in a request in order to execute code. The secret is stored in a temporary file at [`os.tmpdir()`](http://nodejs.org/api/os.html#os_os_tmpdir) and removed right after the config has been loaded into memory.
That's all just security on top. Needless to say that your production server shouldn't expose arbitrary ports anyway.
**I strongly recommend to call** `phridge.disposeAll()` **when the node process exits as this is the only way to ensure that all child processes terminate as well.** Since `disposeAll()` is async it is not safe to call it on `process.on("exit")`. It is better to call it on `SIGINT`, `SIGTERM` and within your regular exit flow.
<br />
Expand All @@ -305,17 +296,9 @@ Spawns a new PhantomJS process with the given config. [Read the PhantomJS docume
Terminates all PhantomJS processes that have been spawned. The promise will be fulfilled when all child processes emitted an `exit`-event.
### .config.minPort: Number = 2000
The minimum port where phridge will try to bind an http server.
### .config.maxPort: Number = 65536
The maximum port where phridge will try to bind an http server.
### .config.stdout: Stream = process.stdout
Destination stream where PhantomJS' stdout will be piped to. Set it `null` if you don't want it. Changing the value does not affect processes that have already been spawned.
Destination stream where PhantomJS' [clean stdout](#phantom-childprocess-cleanstdout) will be piped to. Set it `null` if you don't want it. Changing the value does not affect processes that have already been spawned.
### .config.stderr: Stream = process.stderr
Expand All @@ -327,15 +310,11 @@ Destination stream where PhantomJS' stderr will be piped to. Set it `null` if yo
### .childProcess: ChildProcess
A reference to node's [ChildProcess](http://nodejs.org/api/child_process.html#child_process_class_childprocess).
### .port: Number
Actual port the process listens for http requests.
A reference to the [ChildProcess](http://nodejs.org/api/child_process.html#child_process_class_childprocess)-instance.
### .secret: String
### <a name="phantom-childprocess-cleanstdout"></a> .childProcess.cleanStdout: ReadableStream
The shared secret between node and PhantomJS. See also [A note on security](#a-note-on-security).
phridge extends the [ChildProcess](http://nodejs.org/api/child_process.html#child_process_class_childprocess)-instance by a new stream called `cleanStdout`. This stream is piped to `process.stdout` by default. It provides all data not dedicated to phridge. Streaming data is considered to be dedicated to phridge when the new line is preceded by the classifier string `"message to node: "`.
### <a name="phantom-run"></a>.run(args..., fn): Promise → *
Expand All @@ -359,7 +338,7 @@ Calls `phantom.exit(0)` inside PhantomJS and resolves when the child process emi
### .phantom: Phantom
A reference to the parent phantom instance.
A reference to the parent [`Phantom`](#api-phantom) instance.
### .run(args..., fn): Promise → *
Expand Down
12 changes: 9 additions & 3 deletions lib/Page.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use strict";

var serializeFn = require("./serializeFn.js"),
phantomMethods = require("./phantom/methods.js");
var serializeFn = require("./serializeFn.js");
var phantomMethods = require("./phantom/methods.js");

var slice = Array.prototype.slice;

Expand Down Expand Up @@ -59,7 +59,13 @@ Page.prototype.run = function (args, fn) {

fn = args.pop();

return this.phantom._request("/page/" + this._id, serializeFn(fn, args));
return this.phantom._send({
action: "run-on-page",
data: {
src: serializeFn(fn, args),
pageId: this._id
}
});
};

/**
Expand Down
Loading

0 comments on commit aa4e46c

Please sign in to comment.