mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1161 lines
38 KiB
1161 lines
38 KiB
NODE(1)
|
|
=======
|
|
Ryan Dahl <ry@tinyclouds.org>
|
|
Version, 0.1.9, 2009.09.05
|
|
|
|
|
|
== Name
|
|
|
|
node - evented I/O for V8 javascript
|
|
|
|
|
|
|
|
== Synopsis
|
|
|
|
An example of a web server written with Node which responds with "Hello
|
|
World" after waiting two seconds:
|
|
|
|
----------------------------------------
|
|
node.http.createServer(function (request, response) {
|
|
setTimeout(function () {
|
|
response.sendHeader(200, {"Content-Type": "text/plain"});
|
|
response.sendBody("Hello World");
|
|
response.finish();
|
|
}, 2000);
|
|
}).listen(8000);
|
|
puts("Server running at http://127.0.0.1:8000/");
|
|
----------------------------------------
|
|
|
|
To run the server, put the code into a file called +example.js+ and execute
|
|
it with the node program
|
|
|
|
----------------------------------------
|
|
> node example.js
|
|
Server running at http://127.0.0.1:8000/
|
|
----------------------------------------
|
|
|
|
|
|
|
|
== API
|
|
|
|
Node supports 3 byte-string encodings: ASCII (+"ascii"+), UTF-8 (+"utf8"+),
|
|
and raw binary (+"raw"+). It uses strings to represent ASCII and UTF-8
|
|
encoded data. For the moment, arrays of integers are used to represent raw
|
|
binary data--this representation is rather inefficient. This will
|
|
change in the future, when
|
|
http://code.google.com/p/v8/issues/detail?id=270[V8 supports Blob objects].
|
|
|
|
Unless otherwise noted, functions are all asynchronous and do not block
|
|
execution.
|
|
|
|
|
|
=== Helpers
|
|
|
|
+puts(string)+::
|
|
Outputs the +string+ and a trailing new-line to +stdout+.
|
|
+
|
|
Everything in node is asynchronous; +puts()+ is no exception. This might
|
|
seem ridiculous but, if for example, one is piping +stdout+ into an NFS
|
|
file, +printf()+ will block from network latency. There is an internal
|
|
queue for +puts()+ output, so you can be assured that output will be
|
|
displayed in the order it was called.
|
|
|
|
|
|
+node.debug(string)+::
|
|
A synchronous output function. Will block the process and
|
|
output the string immediately to stdout.
|
|
|
|
|
|
+p(object)+ ::
|
|
Print the JSON representation of +object+ to the standard output.
|
|
|
|
|
|
+print(string)+::
|
|
Like +puts()+ but without the trailing new-line.
|
|
|
|
|
|
+node.exit(code)+::
|
|
Immediately ends the process with the specified code.
|
|
|
|
+node.cwd()+::
|
|
Returns the current working directory of the process.
|
|
|
|
|
|
=== Global Variables
|
|
|
|
|
|
|
|
+ARGV+ ::
|
|
An array containing the command line arguments.
|
|
|
|
|
|
+__filename+ ::
|
|
The filename of the script being executed.
|
|
|
|
+process+ ::
|
|
A special global object. The +process+ object is like the +window+ object of
|
|
browser-side javascript.
|
|
|
|
|
|
=== Events
|
|
|
|
Many objects in Node emit events: a TCP server emits an event each time
|
|
there is a connection, a child process emits an event when it exits. All
|
|
objects which emit events are are instances of +node.EventEmitter+.
|
|
|
|
Events are represented by a snakecased string. Here are some examples:
|
|
+"connection"+, +"receive"+, +"message_begin"+.
|
|
|
|
Functions can be then be attached to objects, to be executed when an event
|
|
is emitted. These functions are called _listeners_.
|
|
|
|
Some asynchronous file operations return an +EventEmitter+ called a
|
|
_promise_. A promise emits just a single event when the operation is
|
|
complete.
|
|
|
|
==== +node.EventEmitter+
|
|
|
|
All EventEmitters emit the event +"newListener"+ when new listeners are
|
|
added.
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
| Event | Parameters | Notes
|
|
|
|
| +"newListener"+ | +event, listener+| This event is made
|
|
any time someone adds
|
|
a new listener.
|
|
|=========================================================
|
|
|
|
+emitter.addListener(event, listener)+ ::
|
|
Adds a listener to the end of the listeners array for the specified event.
|
|
+
|
|
----------------------------------------
|
|
server.addListener("connection", function (socket) {
|
|
puts("someone connected!");
|
|
});
|
|
----------------------------------------
|
|
|
|
|
|
+emitter.listeners(event)+ ::
|
|
Returns an array of listeners for the specified event. This array can be
|
|
manipulated, e.g. to remove listeners.
|
|
|
|
+emitter.emit(event, args)+ ::
|
|
Execute each of the listeners in order with the array +args+ as arguments.
|
|
|
|
==== +node.Promise+
|
|
|
|
+node.Promise+ inherits from +node.eventEmitter+. A promise emits one of two
|
|
events: +"success"+ or +"error"+. After emitting its event, it will not
|
|
emit anymore events.
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
| Event | Parameters | Notes
|
|
| +"success"+ | (depends) |
|
|
| +"error"+ | (depends) |
|
|
|=========================================================
|
|
|
|
+promise.addCallback(listener)+ ::
|
|
Adds a listener for the +"success"+ event. Returns the same promise object.
|
|
|
|
+promise.addErrback(listener)+ ::
|
|
Adds a listener for the +"error"+ event. Returns the same promise object.
|
|
|
|
+promise.wait()+ ::
|
|
Blocks futher execution until the promise emits a success or error event.
|
|
Events setup before the call to +promise.wait()+ was made may still be
|
|
emitted and executed while +promise.wait()+ is blocking.
|
|
+
|
|
If there was a single argument to the +"success"+ event then it is returned.
|
|
If there were multiple arguments to +"success"+ then they are returned as an
|
|
array.
|
|
+
|
|
If +"error"+ was emitted instead, +wait()+ throws an error.
|
|
+
|
|
*IMPORTANT* +promise.wait()+ is not a true fiber/coroutine. If any other
|
|
promises are created and made to wait while the first promise waits, the
|
|
first promise's wait will not return until all others return. The benefit of
|
|
this is a simple implementation and the event loop does not get blocked.
|
|
Disadvantage is the possibility of situations where the promise stack grows
|
|
infinitely large because promises keep getting created and keep being told
|
|
to wait(). Use +promise.wait()+ sparingly--probably best used only during
|
|
program setup, not during busy server activity.
|
|
|
|
|
|
=== Standard I/O
|
|
|
|
Standard I/O is handled through a special object +node.stdio+. stdout and
|
|
stdin are fully non-blocking (even when piping to files). stderr is
|
|
synchronous.
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
| Event | Parameters | Notes
|
|
|
|
| +"data"+ | +data+ | Made when stdin has received a chunk of data.
|
|
Depending on the encoding that stdin was opened
|
|
with, +data+ will be either an array of integers
|
|
(raw encoding) or a string (ascii or utf8
|
|
encoding). This event will only be emited after
|
|
+node.stdio.open()+ has been called.
|
|
| +"close"+ | | Made when stdin has been closed.
|
|
|=========================================================
|
|
|
|
+node.stdio.open(encoding="utf8")+::
|
|
Open stdin. The program will not exit until +node.stdio.close()+ has been
|
|
called or the +"close"+ event has been emitted.
|
|
|
|
+node.stdio.write(data)+::
|
|
Write data to stdout.
|
|
|
|
+node.stdio.writeError(data)+::
|
|
Write data to stderr. Synchronous.
|
|
|
|
+node.stdio.close()+::
|
|
Close stdin.
|
|
|
|
|
|
=== Modules
|
|
|
|
Node has a simple module loading system. In Node, files and modules are in
|
|
one-to-one correspondence. As an example, +foo.js+ loads the module
|
|
+circle.js+.
|
|
|
|
The contents of +foo.js+:
|
|
|
|
----------------------------------------
|
|
var circle = require("circle.js");
|
|
puts("The area of a cirlce of radius 4 is " + circle.area(4));
|
|
----------------------------------------
|
|
|
|
The contents of +circle.js+:
|
|
|
|
----------------------------------------
|
|
var PI = 3.14;
|
|
|
|
exports.area = function (r) {
|
|
return PI * r * r;
|
|
};
|
|
|
|
exports.circumference = function (r) {
|
|
return 2 * PI * r;
|
|
};
|
|
----------------------------------------
|
|
|
|
The module +circle.js+ has exported the functions +area()+ and
|
|
+circumference()+. To export an object, add to the special +exports+
|
|
object. (Alternatively, one can use +this+ instead of +exports+.) Variables
|
|
local to the module will be private. In this example the variable +PI+ is
|
|
private to +circle.js+.
|
|
|
|
The module path is relative to the file calling +require()+. That is,
|
|
+circle.js+ must be in the same directory as +foo.js+ for +require()+ to
|
|
find it.
|
|
|
|
HTTP URLs can also be used to load modules. For example,
|
|
|
|
----------------------------------------
|
|
var circle = require("http://tinyclouds.org/node/circle.js");
|
|
----------------------------------------
|
|
|
|
Like +require()+ the function +include()+ also loads a module. Instead of
|
|
returning a namespace object, +include()+ will add the module's exports into
|
|
the global namespace. For example:
|
|
|
|
----------------------------------------
|
|
include("circle.js");
|
|
puts("The area of a cirlce of radius 4 is " + area(4));
|
|
----------------------------------------
|
|
|
|
Functions +require_async()+ and +include_async()+ also exist.
|
|
|
|
|
|
==== +process.addListener("exit", function () { })+
|
|
|
|
When the program exits a special object called +process+ will emit an
|
|
+"exit"+ event.
|
|
|
|
The +"exit"+ event cannot perform I/O since the process is going to
|
|
forcably exit in less than microsecond. However, it is a good hook to
|
|
perform constant time checks of the module's state. E.G. for unit tests:
|
|
|
|
----------------------------------------
|
|
include("asserts.js");
|
|
|
|
var timer_executed = false;
|
|
|
|
setTimeout(function () {
|
|
timer_executed = true
|
|
}, 1000);
|
|
|
|
process.addListener("exit", function () {
|
|
assertTrue(timer_executed);
|
|
});
|
|
----------------------------------------
|
|
|
|
Just to reiterate: the +"exit"+ event, is not the place to close files or
|
|
shutdown servers. The process will exit before they get performed.
|
|
|
|
|
|
|
|
=== Timers
|
|
|
|
|
|
+setTimeout(callback, delay)+::
|
|
To schedule execution of callback after delay milliseconds. Returns a
|
|
+timeoutId+ for possible use with +clearTimeout()+.
|
|
|
|
|
|
+clearTimeout(timeoutId)+::
|
|
Prevents said timeout from triggering.
|
|
|
|
|
|
+setInterval(callback, delay)+::
|
|
To schedule the repeated execution of callback everydelay milliseconds. Returns
|
|
a +intervalId+ for possible use with +clearInterval()+.
|
|
|
|
|
|
+clearInterval(intervalId)+::
|
|
Stops a interval from triggering.
|
|
|
|
|
|
=== Child Processes
|
|
|
|
Node provides a tridirectional +popen(3)+ facility through the class
|
|
+node.ChildProcess+. It is possible to stream data through the child's +stdin+,
|
|
+stdout+, and +stderr+ in a fully non-blocking way.
|
|
|
|
==== +node.ChildProcess+
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
|Event |Parameters |Notes
|
|
|
|
|+"output"+ | +data+ |
|
|
Each time the child process sends data to its +stdout+, this event is
|
|
triggered. +data+ is a string. At the moment all data passed to +stdout+ is
|
|
interrpreted as UTF-8 encoded.
|
|
+
|
|
If the child process closes its +stdout+ stream (a common thing to do on
|
|
exit), this event will be emitted with +data === null+.
|
|
|
|
|
|
|+"error"+ | +data+ |
|
|
Identical to the +"output"+ event except for +stderr+ instead of +stdout+.
|
|
|
|
|+"exit"+ | +code+ |
|
|
This event is emitted after the child process ends. +code+ is the final exit
|
|
code of the process. One can be assured that after this event is emitted
|
|
that the +"output"+ and +"error"+ callbacks will no longer be made.
|
|
|
|
|=========================================================
|
|
|
|
+node.createChildProcess(command)+::
|
|
Launches a new process with the given +command+. For example:
|
|
+
|
|
----------------------------------------
|
|
var ls = node.createChildProcess("ls -lh /usr");
|
|
ls.addListener("output", function (data) {
|
|
puts(data);
|
|
});
|
|
----------------------------------------
|
|
|
|
|
|
+child.pid+ ::
|
|
The PID of the child process.
|
|
|
|
|
|
+child.write(data, encoding="ascii")+ ::
|
|
Write data to the child process's +stdin+. The second argument is optional and
|
|
specifies the encoding: possible values are +"utf8"+, +"ascii"+, and +"raw"+.
|
|
|
|
|
|
+child.close()+ ::
|
|
Closes the process's +stdin+ stream.
|
|
|
|
|
|
+child.kill(signal=node.SIGTERM)+ ::
|
|
Send a single to the child process. If no argument is given, the process
|
|
will be sent +node.SIGTERM+. The standard POSIX signals are defined under
|
|
the +node+ namespace (+node.SIGINT+, +node.SIGUSR1+, ...).
|
|
|
|
|
|
|
|
=== File I/O
|
|
|
|
File I/O is provided by simple wrappers around standard POSIX functions.
|
|
All POSIX wrappers have a similar form.
|
|
They return a promise (+node.Promise+). Example:
|
|
|
|
------------------------------------------------------------------------------
|
|
var promise = node.fs.unlink("/tmp/hello");
|
|
promise.addCallback(function () {
|
|
puts("successfully deleted /tmp/hello");
|
|
});
|
|
------------------------------------------------------------------------------
|
|
|
|
There is no guaranteed ordering to the POSIX wrappers. The
|
|
following is very much prone to error
|
|
|
|
------------------------------------------------------------------------------
|
|
node.fs.rename("/tmp/hello", "/tmp/world");
|
|
node.fs.stat("/tmp/world").addCallback(function (stats) {
|
|
puts("stats: " + JSON.stringify(stats));
|
|
});
|
|
------------------------------------------------------------------------------
|
|
|
|
It could be that +stat()+ is executed before the +rename()+.
|
|
The correct way to do this is to chain the promises.
|
|
|
|
------------------------------------------------------------------------------
|
|
node.fs.rename("/tmp/hello", "/tmp/world").addCallback(function () {
|
|
node.fs.stat("/tmp/world").addCallback(function (stats) {
|
|
puts("stats: " + JSON.stringify(stats));
|
|
});
|
|
});
|
|
------------------------------------------------------------------------------
|
|
|
|
Or use the +promise.wait()+ functionality:
|
|
|
|
------------------------------------------------------------------------------
|
|
node.fs.rename("/tmp/hello", "/tmp/world").wait();
|
|
node.fs.stat("/tmp/world").addCallback(function (stats) {
|
|
puts("stats: " + JSON.stringify(stats));
|
|
});
|
|
------------------------------------------------------------------------------
|
|
|
|
+node.fs.rename(path1, path2)+ ::
|
|
See rename(2).
|
|
- on success: no parameters.
|
|
- on error: no parameters.
|
|
|
|
|
|
|
|
+node.fs.stat(path)+ ::
|
|
See stat(2).
|
|
- on success: Returns +stats+ object. It looks like this:
|
|
+{ dev: 2049, ino: 305352, mode: 16877, nlink: 12, uid: 1000, gid: 1000,
|
|
rdev: 0, size: 4096, blksize: 4096, blocks: 8, atime:
|
|
"2009-06-29T11:11:55Z", mtime: "2009-06-29T11:11:40Z", ctime:
|
|
"2009-06-29T11:11:40Z" }+
|
|
- on error: no parameters.
|
|
|
|
+node.fs.unlink(path)+ ::
|
|
See unlink(2)
|
|
- on success: no parameters.
|
|
- on error: no parameters.
|
|
|
|
|
|
+node.fs.rmdir(path)+ ::
|
|
See rmdir(2)
|
|
- on success: no parameters.
|
|
- on error: no parameters.
|
|
|
|
+node.fs.mkdir(path, mode)+ ::
|
|
See mkdir(2)
|
|
- on success: no parameters.
|
|
- on error: no parameters.
|
|
|
|
+node.fs.readdir(path)+ ::
|
|
Reads the contents of a directory.
|
|
- on success: One argument, an array containing the names (strings) of the
|
|
files in the directory (excluding "." and "..").
|
|
- on error: no parameters.
|
|
|
|
|
|
+node.fs.close(fd)+ ::
|
|
See close(2)
|
|
- on success: no parameters.
|
|
- on error: no parameters.
|
|
|
|
|
|
+node.fs.open(path, flags, mode)+::
|
|
See open(2). The constants like +O_CREAT+ are defined at +node.O_CREAT+.
|
|
- on success: +fd+ is given as the parameter.
|
|
- on error: no parameters.
|
|
|
|
|
|
+node.fs.write(fd, data, position)+::
|
|
Write data to the file specified by +fd+. +data+ is either an array of
|
|
integers (for raw data) or a string for UTF-8 encoded characters.
|
|
+position+ refers to the offset from the beginning of the file where this
|
|
data should be written. If +position+ is +null+, the data will be written at
|
|
the current position. See pwrite(2).
|
|
- on success: returns an integer +written+ which specifies how many _bytes_ were written.
|
|
- on error: no parameters.
|
|
|
|
|
|
+node.fs.read(fd, length, position, encoding)+::
|
|
|
|
Read data from the file specified by +fd+.
|
|
+
|
|
+length+ is an integer specifying the number of
|
|
bytes to read.
|
|
+
|
|
+position+ is an integer specifying where to begin
|
|
reading from in the file.
|
|
+
|
|
+encoding+ is either +node.UTF8+
|
|
or +node.RAW+.
|
|
+
|
|
- on success: returns +data, bytes_read+, what was read from the file.
|
|
- on error: no parameters.
|
|
|
|
+node.fs.cat(filename, encoding)+::
|
|
|
|
Outputs the entire contents of a file. Example:
|
|
+
|
|
--------------------------------
|
|
node.fs.cat("/etc/passwd", "utf8").addCallback(function (content) {
|
|
puts(content);
|
|
});
|
|
--------------------------------
|
|
+
|
|
- on success: returns +data+, what was read from the file.
|
|
- on error: no parameters.
|
|
|
|
|
|
=== HTTP
|
|
|
|
The HTTP interfaces in Node are designed to support many features
|
|
of the protocol which have been traditionally difficult to use.
|
|
In particular, large, possibly chunk-encoded, messages. The interface is
|
|
careful to never buffer entire requests or responses--the
|
|
user is able to stream data.
|
|
|
|
HTTP message headers are represented by an object like this
|
|
|
|
----------------------------------------
|
|
{ "Content-Length": "123"
|
|
, "Content-Type": "text/plain"
|
|
, "Connection": "keep-alive"
|
|
, "Accept": "*/*"
|
|
}
|
|
----------------------------------------
|
|
|
|
In order to support the full spectrum of possible HTTP applications, Node's
|
|
HTTP API is very low-level. It deals with connection handling and message
|
|
parsing only. It parses a message into headers and body but it does not
|
|
parse the actual headers or the body. That means, for example, that Node
|
|
does not, and will never, provide API to access or manipulate Cookies or
|
|
multi-part bodies. _This is left to the user._
|
|
|
|
|
|
==== +node.http.Server+
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
|Event | Parameters | Notes
|
|
|
|
|+"request"+ | +request, response+ |
|
|
+request+ is an instance of +node.http.ServerRequest+
|
|
+
|
|
+response+ is an instance of +node.http.ServerResponse+
|
|
|
|
|+"connection"+ | +connection+ |
|
|
When a new TCP connection is established.
|
|
+connection+ is an object of type +node.http.Connection+. Usually users will not
|
|
want to access this event. The +connection+ can also be accessed at
|
|
+request.connection+.
|
|
|
|
|+"close"+ | +errorno+ | Emitted when the server closes. +errorno+
|
|
is an integer which indicates what, if any,
|
|
error caused the server to close. If no
|
|
error occured +errorno+ will be 0.
|
|
|
|
|=========================================================
|
|
|
|
+node.http.createServer(request_listener, options);+ ::
|
|
Returns a new web server object.
|
|
+
|
|
The +options+ argument is optional. The
|
|
+options+ argument accepts the same values as the
|
|
options argument for +node.tcp.Server+ does.
|
|
+
|
|
The +request_listener+ is a function which is automatically
|
|
added to the +"request"+ event.
|
|
|
|
+server.listen(port, hostname)+ ::
|
|
Begin accepting connections on the specified port and hostname.
|
|
If the hostname is omitted, the server will accept connections
|
|
directed to any address. This function is synchronous.
|
|
|
|
+server.close()+ ::
|
|
Stops the server from accepting new connections.
|
|
|
|
|
|
|
|
==== +node.http.ServerRequest+
|
|
|
|
This object is created internally by a HTTP server--not by
|
|
the user--and passed as the first argument to a +"request"+ listener.
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
|Event | Parameters | Notes
|
|
|
|
|+"body"+ | +chunk+ |
|
|
Emitted when a piece of the message body is received. Example: A chunk of
|
|
the body is given as the single argument. The transfer-encoding has been
|
|
decoded. The body chunk is either a String in the case of UTF-8 encoding or
|
|
an array of numbers in the case of raw encoding. The body encoding is set
|
|
with +request.setBodyEncoding()+.
|
|
|
|
|+"complete"+ | |
|
|
Emitted exactly once for each message. No arguments.
|
|
After emitted no other events will be emitted on the request.
|
|
|
|
|=========================================================
|
|
|
|
+request.method+ ::
|
|
The request method as a string. Read only. Example:
|
|
+"GET"+, +"DELETE"+.
|
|
|
|
|
|
+request.uri+ ::
|
|
Request URI Object. This contains only the parameters that are
|
|
present in the actual http request. That is, if the request is
|
|
+
|
|
----------------------------------------
|
|
GET /status?name=ryan HTTP/1.1\r\n
|
|
Accept: */*\r\n
|
|
\r\n
|
|
----------------------------------------
|
|
+
|
|
Then +request.uri+ will be
|
|
+
|
|
----------------------------------------
|
|
{ path: "/status",
|
|
file: "status",
|
|
directory: "/",
|
|
params: { "name" : "ryan" }
|
|
}
|
|
----------------------------------------
|
|
+
|
|
In particular, note that +request.uri.protocol+ is
|
|
+undefined+. This is because there was no URI protocol given
|
|
in the actual HTTP Request.
|
|
+
|
|
+request.uri.anchor+, +request.uri.query+, +request.uri.file+, +request.uri.directory+, +request.uri.path+, +request.uri.relative+, +request.uri.port+, +request.uri.host+, +request.uri.password+, +request.uri.user+, +request.uri.authority+, +request.uri.protocol+, +request.uri.params+, +request.uri.toString()+, +request.uri.source+
|
|
|
|
|
|
+request.headers+ ::
|
|
Read only.
|
|
|
|
|
|
+request.httpVersion+ ::
|
|
The HTTP protocol version as a string. Read only. Examples:
|
|
+"1.1"+, +"1.0"+
|
|
|
|
|
|
+request.setBodyEncoding(encoding)+ ::
|
|
Set the encoding for the request body. Either +"utf8"+ or +"raw"+. Defaults
|
|
to raw.
|
|
|
|
|
|
+request.pause()+ ::
|
|
Pauses request from emitting events. Useful to throttle back an upload.
|
|
|
|
|
|
+request.resume()+ ::
|
|
Resumes a paused request.
|
|
|
|
|
|
+request.connection+ ::
|
|
The +node.http.Connection+ object.
|
|
|
|
|
|
==== +node.http.ServerResponse+
|
|
|
|
This object is created internally by a HTTP server--not by the user. It is
|
|
passed as the second parameter to the +"request"+ event.
|
|
|
|
+response.sendHeader(statusCode, headers)+ ::
|
|
|
|
Sends a response header to the request. The status code is a 3-digit HTTP
|
|
status code, like +404+. The second argument, +headers+ are the response headers.
|
|
+
|
|
Example:
|
|
+
|
|
----------------------------------------
|
|
var body = "hello world";
|
|
response.sendHeader(200, {
|
|
"Content-Length": body.length,
|
|
"Content-Type": "text/plain"
|
|
});
|
|
----------------------------------------
|
|
+
|
|
This method must only be called once on a message and it must
|
|
be called before +response.finish()+ is called.
|
|
|
|
+response.sendBody(chunk, encoding="ascii")+ ::
|
|
|
|
This method must be called after +sendHeader+ was
|
|
called. It sends a chunk of the response body. This method may
|
|
be called multiple times to provide successive parts of the body.
|
|
+
|
|
If +chunk+ is a string, the second parameter
|
|
specifies how to encode it into a byte stream. By default the
|
|
+encoding+ is +"ascii"+.
|
|
+
|
|
Note: This is the raw HTTP body and has nothing to do with
|
|
higher-level multi-part body encodings that may be used.
|
|
|
|
|
|
+response.finish()+ ::
|
|
This method signals to the server that all of the response headers and body
|
|
has been sent; that server should consider this message complete.
|
|
The method, +response.finish()+, MUST be called on each
|
|
response.
|
|
|
|
|
|
|
|
==== +node.http.Client+
|
|
|
|
An HTTP client is constructed with a server address as its
|
|
argument, the returned handle is then used to issue one or more
|
|
requests. Depending on the server connected to, the client might
|
|
pipeline the requests or reestablish the connection after each
|
|
connection. _Currently the implementation does not pipeline requests._
|
|
|
|
Example of connecting to +google.com+
|
|
|
|
----------------------------------------
|
|
var google = node.http.createClient(80, "google.com");
|
|
var request = google.get("/");
|
|
request.finish(function (response) {
|
|
puts("STATUS: " + response.statusCode);
|
|
puts("HEADERS: " + JSON.stringify(response.headers));
|
|
response.setBodyEncoding("utf8");
|
|
response.addListener("body", function (chunk) {
|
|
puts("BODY: " + chunk);
|
|
});
|
|
});
|
|
----------------------------------------
|
|
|
|
+node.http.createClient(port, host)+ ::
|
|
|
|
Constructs a new HTTP client. +port+ and
|
|
+host+ refer to the server to be connected to. A
|
|
connection is not established until a request is issued.
|
|
|
|
+client.get(path, request_headers)+, +client.head(path, request_headers)+, +client.post(path, request_headers)+, +client.del(path, request_headers)+, +client.put(path, request_headers)+ ::
|
|
|
|
Issues a request; if necessary establishes connection. Returns a +node.http.ClientRequest+ instance.
|
|
+
|
|
+request_headers+ is optional.
|
|
Additional request headers might be added internally
|
|
by Node. Returns a +ClientRequest+ object.
|
|
+
|
|
Do remember to include the +Content-Length+ header if you
|
|
plan on sending a body. If you plan on streaming the body, perhaps
|
|
set +Transfer-Encoding: chunked+.
|
|
+
|
|
NOTE: the request is not complete. This method only sends
|
|
the header of the request. One needs to call
|
|
+request.finish()+ to finalize the request and retrieve
|
|
the response. (This sounds convoluted but it provides a chance
|
|
for the user to stream a body to the server with
|
|
+request.sendBody()+.)
|
|
|
|
|
|
==== +node.http.ClientRequest+
|
|
|
|
This object is created internally and returned from the request methods of a
|
|
+node.http.Client+. It represents an _in-progress_ request whose header has
|
|
already been sent.
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
|Event | Parameters | Notes
|
|
|+"response"+ | +response+ |
|
|
Emitted when a response is received to this request. Typically the user will
|
|
set a listener to this via the +request.finish()+ method.
|
|
+
|
|
This event is emitted only once.
|
|
+
|
|
The +response+ argument will be an instance of +node.http.ClientResponse+.
|
|
|=========================================================
|
|
|
|
|
|
+request.sendBody(chunk, encoding="ascii")+ ::
|
|
|
|
Sends a sucessive peice of the body. By calling this method
|
|
many times, the user can stream a request body to a
|
|
server—in that case it is suggested to use the
|
|
+["Transfer-Encoding", "chunked"]+ header line when
|
|
creating the request.
|
|
+
|
|
The +chunk+ argument should be an array of integers
|
|
or a string.
|
|
+
|
|
The +encoding+ argument is optional and only
|
|
applies when +chunk+ is a string. The encoding
|
|
argument should be either +"utf8"+ or
|
|
+"ascii"+. By default the body uses ASCII encoding,
|
|
as it is faster.
|
|
|
|
|
|
+request.finish(response_listener)+ ::
|
|
|
|
Finishes sending the request. If any parts of the body are
|
|
unsent, it will flush them to the socket. If the request is
|
|
chunked, this will send the terminating +"0\r\n\r\n"+.
|
|
+
|
|
The parameter +response_listener+ is a callback which
|
|
will be executed when the response headers have been received.
|
|
The +response_listener+ callback is executed with one
|
|
argument which is an instance of +node.http.ClientResponse+.
|
|
|
|
|
|
|
|
==== +node.http.ClientResponse+
|
|
|
|
This object is created internally and passed to the +"response"+ event.
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
|Event | Parameters | Notes
|
|
|
|
|+"body"+ | +chunk+ |
|
|
Emitted when a piece of the message body is received. Example: A chunk of
|
|
the body is given as the single argument. The transfer-encoding has been
|
|
decoded. The body chunk is either a String in the case of UTF-8 encoding or
|
|
an array of numbers in the case of raw encoding. The body encoding is set
|
|
with +response.setBodyEncoding()+.
|
|
|
|
|+"complete"+ | |
|
|
Emitted exactly once for each message. No arguments.
|
|
After emitted no other events will be emitted on the response.
|
|
|
|
|=========================================================
|
|
|
|
+response.statusCode+ ::
|
|
The 3-digit HTTP response status code. E.G. +404+.
|
|
|
|
+response.httpVersion+ ::
|
|
The HTTP version of the connected-to server. Probably either
|
|
+"1.1"+ or +"1.0"+.
|
|
|
|
+response.headers+ ::
|
|
The response headers.
|
|
|
|
+response.setBodyEncoding(encoding)+ ::
|
|
Set the encoding for the response body. Either +"utf8"+ or +"raw"+.
|
|
Defaults to raw.
|
|
|
|
+response.pause()+ ::
|
|
Pauses response from emitting events. Useful to throttle back a download.
|
|
|
|
+response.resume()+ ::
|
|
Resumes a paused response.
|
|
|
|
+response.client+ ::
|
|
A reference to the +node.http.Client+ that this response belongs to.
|
|
|
|
|
|
|
|
=== TCP
|
|
|
|
==== +node.tcp.Server+
|
|
|
|
Here is an example of a echo server which listens for connections
|
|
on port 7000
|
|
|
|
----------------------------------------
|
|
function echo (socket) {
|
|
socket.setEncoding("utf8");
|
|
socket.addListener("connect", function () {
|
|
socket.send("hello\r\n");
|
|
});
|
|
socket.addListener("receive", function (data) {
|
|
socket.send(data);
|
|
});
|
|
socket.addListener("eof", function () {
|
|
socket.send("goodbye\r\n");
|
|
socket.close();
|
|
});
|
|
}
|
|
var server = node.tcp.createServer(echo);
|
|
server.listen(7000, "localhost");
|
|
----------------------------------------
|
|
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
|Event | Parameters | Notes
|
|
|+"connection"+ | +connection+ | Emitted when a new connection is made.
|
|
+connection+ is an instance of +node.tcp.Connection+.
|
|
|+"close"+ | +errorno+ | Emitted when the server closes. +errorno+
|
|
is an integer which indicates what, if any,
|
|
error caused the server to close. If no
|
|
error occured +errorno+ will be 0.
|
|
|=========================================================
|
|
|
|
+node.tcp.createServer(connection_listener);+ ::
|
|
Creates a new TCP server.
|
|
+
|
|
The +connection_listener+ argument is automatically set as a listener for
|
|
the +"connection"+ event.
|
|
|
|
|
|
+server.listen(port, host=null, backlog=1024)+ ::
|
|
Tells the server to listen for TCP connections to +port+ and +host+.
|
|
+
|
|
+host+ is optional. If +host+ is not specified the server will accept client
|
|
connections on any network address.
|
|
+
|
|
The third argument, +backlog+, is also optional and defaults to 1024. The
|
|
+backlog+ argument defines the maximum length to which the queue of pending
|
|
connections for the server may grow.
|
|
+
|
|
This function is synchronous.
|
|
|
|
|
|
+server.close()+::
|
|
Stops the server from accepting new connections. This function is
|
|
asynchronous, the server is finally closed when the server emits a +"close"+
|
|
event.
|
|
|
|
|
|
==== +node.tcp.Connection+
|
|
|
|
This object is used as a TCP client and also as a server-side
|
|
socket for +node.tcp.Server+.
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
|Event | Parameters | Notes
|
|
|+"connect"+ | | Call once the connection is established
|
|
after a call to +createConnection()+ or
|
|
+connect()+.
|
|
|+"receive"+ | +data+ | Called when data is received on the
|
|
connection. Encoding of data is set
|
|
by +connection.setEncoding()+. +data+
|
|
will either be a string, in the case of
|
|
utf8, or an array of integer in the case
|
|
of raw encoding.
|
|
|+"eof"+ | | Called when the other end of the
|
|
connection sends a FIN packet.
|
|
After this is emitted the +readyState+
|
|
will be +"writeOnly"+. One should probably
|
|
just call +connection.close()+ when this
|
|
event is emitted.
|
|
|+"timeout"+ | | Emitted if the connection times out from
|
|
inactivity. The +"close"+ event will be
|
|
emitted immediately following this event.
|
|
|+"close"+ | +had_error+ | Emitted once the connection is fully
|
|
closed. The argument +had_error+
|
|
is a boolean which says if the connection
|
|
was closed due to a transmission error.
|
|
(TODO: access error codes.)
|
|
|=========================================================
|
|
|
|
+node.tcp.createConnection(port, host="127.0.0.1")+::
|
|
Creates a new connection object and opens a connection to the specified
|
|
+port+ and +host+. If the second parameter is omitted, localhost is assumed.
|
|
+
|
|
When the connection is established the +"connect"+ event will be emitted.
|
|
|
|
+connection.connect(port, host="127.0.0.1")+::
|
|
Opens a connection to the specified +port+ and +host+. +createConnection()+
|
|
also opens a connection; normally this method is not needed. Use this only
|
|
if a connection is closed and you want to reuse the object to connect to
|
|
another server.
|
|
+
|
|
This function is asynchronous. When the +"connect"+ event is emitted the
|
|
connection is established. If there is a problem connecting, the +"connect"+
|
|
event will not be emitted, the +"close"+ event will be emitted with
|
|
+had_error == true+.
|
|
|
|
+connection.remoteAddress+::
|
|
The string representation of the remote IP address. For example,
|
|
+"74.125.127.100"+ or +"2001:4860:a005::68"+.
|
|
+
|
|
This member is only present in server-side connections.
|
|
|
|
|
|
+connection.readyState+::
|
|
Either +"closed"+, +"open"+, +"opening"+, +"readOnly"+, or +"writeOnly"+.
|
|
|
|
|
|
+connection.setEncoding(encoding)+::
|
|
Sets the encoding (either +"utf8"+ or +"raw"+) for data that is received.
|
|
|
|
+connection.send(data, encoding="ascii")+::
|
|
Sends data on the connection. The data should be eithre an array
|
|
of integers (for raw binary) or a string (for utf8 or ascii).
|
|
The second parameter specifies the encoding in the case of a
|
|
string--it defaults to ASCII because encoding to UTF8 is
|
|
rather slow.
|
|
|
|
|
|
+connection.close()+::
|
|
Half-closes the connection. I.E. sends a FIN packet. It is
|
|
possible the server will still send some data. After calling
|
|
this +readyState+ will be +"readOnly"+.
|
|
|
|
|
|
+connection.forceClose()+::
|
|
Ensures that no more I/O activity happens on this socket. Only
|
|
necessary in case of errors (parse error or so).
|
|
|
|
+connection.readPause()+::
|
|
Pauses the reading of data. That is, +"receive"+ events will not be emitted.
|
|
Useful to throttle back an upload.
|
|
|
|
+connection.readResume()+::
|
|
Resumes reading if reading was paused by +readPause()+.
|
|
|
|
+connection.setTimeout(timeout)+::
|
|
Sets the connection to timeout after +timeout+ milliseconds of inacitivty on
|
|
the connection. By default all +node.tcp.Connection+ objects have a timeout
|
|
of 60 seconds (60000 ms).
|
|
+
|
|
If +timeout+ is 0, then the idle timeout is disabled.
|
|
|
|
|
|
=== DNS
|
|
|
|
Here is an example of which resolves +"www.google.com"+ then reverse
|
|
resolves the IP addresses which are returned.
|
|
|
|
-------------------------------------------------------------------------
|
|
var resolution = node.dns.resolve4("www.google.com");
|
|
|
|
resolution.addCallback(function (addresses, ttl, cname) {
|
|
puts("addresses: " + JSON.stringify(addresses));
|
|
puts("ttl: " + JSON.stringify(ttl));
|
|
puts("cname: " + JSON.stringify(cname));
|
|
|
|
for (var i = 0; i < addresses.length; i++) {
|
|
var a = addresses[i];
|
|
var reversing = node.dns.reverse(a);
|
|
reversing.addCallback( function (domains, ttl, cname) {
|
|
puts("reverse for " + a + ": " + JSON.stringify(domains));
|
|
});
|
|
reversing.addErrback( function (code, msg) {
|
|
puts("reverse for " + a + " failed: " + msg);
|
|
});
|
|
}
|
|
});
|
|
|
|
resolution.addErrback(function (code, msg) {
|
|
puts("error: " + msg);
|
|
});
|
|
-------------------------------------------------------------------------
|
|
|
|
|
|
+node.dns.resolve4(domain)+::
|
|
|
|
Resolves a domain (e.g. +"google.com"+) into an array of IPv4 addresses (e.g.
|
|
+["74.125.79.104", "74.125.79.105", "74.125.79.106"]+).
|
|
This function returns a promise.
|
|
- on success: returns +addresses, ttl, cname+. +ttl+ (time-to-live) is an integer
|
|
specifying the number of seconds this result is valid for. +cname+ is the
|
|
canonical name for the query.
|
|
- on error: returns +code, msg+. +code+ is one of the error codes listed
|
|
below and +msg+ is a string describing the error in English.
|
|
|
|
+node.dns.resolve6(domain)+::
|
|
|
|
The same as +node.dns.resolve4()+ except for IPv6 queries (an +AAAA+ query).
|
|
|
|
+node.dns.reverse(ip)+::
|
|
|
|
Reverse resolves an ip address to an array of domain names.
|
|
|
|
- on success: returns +domains, ttl, cname+. +ttl+ (time-to-live) is an integer
|
|
specifying the number of seconds this result is valid for. +cname+ is the
|
|
canonical name for the query. +domains+ is an array of domains.
|
|
- on error: returns +code, msg+. +code+ is one of the error codes listed
|
|
below and +msg+ is a string describing the error in English.
|
|
|
|
|
|
Each DNS query can return an error code.
|
|
|
|
- +node.dns.TEMPFAIL+: timeout, SERVFAIL or similar.
|
|
- +node.dns.PROTOCOL+: got garbled reply.
|
|
- +node.dns.NXDOMAIN+: domain does not exists.
|
|
- +node.dns.NODATA+: domain exists but no data of reqd type.
|
|
- +node.dns.NOMEM+: out of memory while processing.
|
|
- +node.dns.BADQUERY+: the query is malformed.
|
|
|
|
|
|
|
|
== Extension API
|
|
|
|
External modules can be compiled and dynamically linked into Node.
|
|
Node is more or less glue between several C and C++ libraries:
|
|
|
|
- V8 Javascript, a C++ library. Used for interfacing with Javascript:
|
|
creating objects, calling functions, etc. Documented mostly in the
|
|
+v8.h+ header file (+deps/v8/include/v8.h+ in the Node source tree).
|
|
|
|
- libev, C event loop library. Anytime one needs to wait for a file
|
|
descriptor to become readable, wait for a timer, or wait for a signal to
|
|
received one will need to interface with libev. That is, if you perform
|
|
any I/O, libev will need to be used. Node uses the +EV_DEFAULT+ event
|
|
loop. Documentation can be found http:/cvs.schmorp.de/libev/ev.html[here].
|
|
|
|
- libeio, C thread pool library. Used to execute blocking POSIX system
|
|
calls asynchronously. Mostly wrappers already exist for such calls, in
|
|
+src/file.cc+ so you will probably not need to use it. If you do need it,
|
|
look at the header file +deps/libeio/eio.h+.
|
|
|
|
- Internal Node libraries. Most importantly is the +node::EventEmitter+
|
|
class which you will likely want to derive from.
|
|
|
|
- Others. Look in +deps/+ for what else is available.
|
|
|
|
Node statically compiles all its dependencies into the executable. When
|
|
compiling your module, you don't need to worry about linking to any of these
|
|
libraries.
|
|
|
|
Here is a sample Makefile taken from
|
|
http://github.com/ry/node_postgres[node_postgres]:
|
|
-----------------------------------------------------
|
|
binding.node: binding.o Makefile
|
|
gcc -shared -o binding.node binding.o \
|
|
-L`pg_config --libdir` -lpq
|
|
|
|
binding.o: binding.cc Makefile
|
|
gcc `node --cflags` -I`pg_config --includedir` \
|
|
binding.cc -c -o binding.o
|
|
|
|
clean:
|
|
rm -f binding.o binding.node
|
|
.PHONY: clean
|
|
-----------------------------------------------------
|
|
As you can see, the only thing your module needs to know about Node is the
|
|
CFLAGS that node was compiled with which are gotten from +node --cflags+
|
|
If you want to make a debug build, then use +node_g --cflags+. (+node_g+ is
|
|
the debug build of node, which can built with +configure --debug; make; make
|
|
install+.)
|
|
|
|
Node extension modules are dynamically linked libraries with a +.node+
|
|
extension. Node opens this file and looks for a function called +init()+
|
|
which must be of the form:
|
|
|
|
-----------------------------------------------------
|
|
extern "C" void init (Handle<Object> target)
|
|
-----------------------------------------------------
|
|
|
|
In this function you can create new javascript objects and attach them to
|
|
+target+. Here is a very simple module:
|
|
|
|
-----------------------------------------------------
|
|
extern "C" void
|
|
init (Handle<Object> target)
|
|
{
|
|
HandleScope scope;
|
|
target->Set(String::New("hello"), String::New("World"));
|
|
}
|
|
-----------------------------------------------------
|
|
|
|
Further documentation will come soon. For now see the source code of
|
|
http://github.com/ry/node_postgres[node_postgres].
|
|
|
|
// vim: set syntax=asciidoc:
|
|
|