mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
1283 lines
42 KiB
Plaintext
1283 lines
42 KiB
Plaintext
NODE(1)
|
|
=======
|
|
Ryan Dahl <ry@tinyclouds.org>
|
|
Version, 0.1.13, 2009.09.30
|
|
|
|
|
|
== NAME
|
|
|
|
node - evented I/O for V8 javascript
|
|
|
|
|
|
|
|
== SYNOPSIS
|
|
|
|
An example of a web server written with Node which responds with "Hello
|
|
World":
|
|
|
|
----------------------------------------
|
|
include("/utils.js");
|
|
include("/http.js");
|
|
createServer(function (request, response) {
|
|
response.sendHeader(200, {"Content-Type": "text/plain"});
|
|
response.sendBody("Hello World\n");
|
|
response.finish();
|
|
}).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 string encodings. UTF-8 (+"utf8"+), ASCII (+"ascii"+), and
|
|
Binary (+"binary"+). +"ascii"+ and +"binary"+ only look at the first 8 bits
|
|
of the 16bit javascript string characters. Both are relatively fast--use
|
|
them if you can. +"utf8"+ is slower and should be avoided when possible.
|
|
|
|
Unless otherwise noted, functions are all asynchronous and do not block
|
|
execution.
|
|
|
|
|
|
=== Helpers
|
|
|
|
These objects are available to all programs.
|
|
|
|
+node.cwd()+::
|
|
Returns the current working directory of the process.
|
|
|
|
+node.compile(source, scriptOrigin)+::
|
|
Just like +eval()+ except that you can specify a +scriptOrigin+ for better
|
|
error reporting.
|
|
|
|
+__filename+ ::
|
|
The filename of the script being executed.
|
|
|
|
+require(path)+ ::
|
|
+include(path)+ ::
|
|
See the modules section.
|
|
|
|
+node.libraryPaths+ ::
|
|
The search path for absolute path arguments to +require()+ and +include()+.
|
|
|
|
=== The +process+ Object
|
|
|
|
+process+ is the equivalent of +window+ in browser-side javascript. It is
|
|
the global scope. +process+ is an instance of +node.EventEmitter+.
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
| Event | Parameters | Notes
|
|
| +"exit"+ | +code+ | Made when the process exits.
|
|
A listener on this event should not try to perform
|
|
I/O since the process will forcibly exit in less
|
|
than microsecond. However, it is a good hook to
|
|
perform constant time checks of the module's
|
|
state (like for unit tests).
|
|
+
|
|
The parameter +code+ is the integer exit code
|
|
passed to +process.exit()+.
|
|
|=========================================================
|
|
|
|
+process.exit(code=0)+::
|
|
Ends the process with the specified code. By default it exits with the
|
|
success code 0.
|
|
|
|
+process.ARGV+ ::
|
|
An array containing the command line arguments.
|
|
|
|
+process.ENV+ ::
|
|
An object containing the user environment. See environ(7).
|
|
|
|
|
|
=== Utilities
|
|
|
|
These function are in +"/utils.js"+. Use +require("/utils.js")+ to access them.
|
|
|
|
+puts(string)+::
|
|
Outputs the +string+ and a trailing new-line to +stdout+.
|
|
|
|
+print(string)+::
|
|
Like +puts()+ but without the trailing new-line.
|
|
|
|
+debug(string)+::
|
|
A synchronous output function. Will block the process and
|
|
output the string immediately to stdout.
|
|
|
|
+inspect(object)+ ::
|
|
Return a string representation of the +object+. (For debugging.)
|
|
|
|
+exec(command)+::
|
|
Executes the command as a child process, buffers the output and returns it
|
|
in a promise callback.
|
|
+
|
|
----------------------------------------
|
|
include("/utils.js");
|
|
exec("ls /").addCallback(function (stdout, stderr) {
|
|
puts(stdout);
|
|
});
|
|
----------------------------------------
|
|
+
|
|
- on success: stdout buffer, stderr buffer
|
|
- on error: exit code, stdout buffer, stderr buffer
|
|
|
|
|
|
|
|
=== 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 camel-cased string. Here are some examples:
|
|
+"connection"+, +"receive"+, +"messageBegin"+.
|
|
|
|
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, arg1, arg2, ...)+ ::
|
|
Execute each of the listeners in order with the supplied 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.emitSuccess(arg1, arg2, ...)+ ::
|
|
If you created the promise (by doing +new node.Promise()+) then call
|
|
+emitSuccess+ to emit the +"success"+ event with the given arguments.
|
|
+
|
|
(+promise.emit("success", arg1, arg2, ...)+ should also work, but doesn't at
|
|
the moment due to a bug; use +emitSuccess+ instead.)
|
|
|
|
+promise.emitError(arg1, arg2, ...)+ ::
|
|
Emits the +"error"+ event.
|
|
|
|
+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 a string. 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");
|
|
include("/utils.js");
|
|
puts("The area of a circle 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 function +puts()+ comes from the module
|
|
+"/utils.js"+. Because +include("/utils.js")+ was called, +puts()+ is in the
|
|
global namespace.
|
|
|
|
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.
|
|
|
|
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");
|
|
include("/utils.js");
|
|
puts("The area of a cirlce of radius 4 is " + area(4));
|
|
----------------------------------------
|
|
|
|
When an absolute path is given to +require()+ or +include()+, like
|
|
+require("/mjsunit.js")+ the module is searched for in the
|
|
+node.libraryPaths+ array. +node.libraryPaths+ on my system looks like this:
|
|
|
|
----------------------------------------
|
|
[ "/home/ryan/.node_libraries"
|
|
, "/home/ryan/local/node/lib/node_libraries"
|
|
, "/"
|
|
]
|
|
----------------------------------------
|
|
|
|
That is, first Node looks for +"/home/ryan/.node_libraries/mjsunit.js"+ and
|
|
then for +"/home/ryan/local/node/lib/node_libraries/mjsunit.js"+. If not
|
|
found, it finally looks for +"/mjsunit.js"+ (in the root directory).
|
|
|
|
+node.libraryPaths+ can be modified at runtime by simply unshifting new
|
|
paths on to it and at startup with the +NODE_LIBRARY_PATHS+ environmental
|
|
variable (which should be a list of paths, colon separated).
|
|
|
|
Node comes with several libraries which are installed when +"make install"+
|
|
is run. These are currently undocumented, but do look them up in your
|
|
system.
|
|
|
|
|
|
|
|
|
|
=== 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 every +delay+ 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
|
|
emitted. +data+ is a string. + 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
|
|
+"binary"+.
|
|
|
|
|
|
+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 +node.fs.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" }+
|
|
See the +node.fs.Stats+ section below for more information.
|
|
- 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, encoding)+::
|
|
Write data to the file specified by +fd+. +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.
|
|
+
|
|
- on success: returns +data, bytes_read+, what was read from the file.
|
|
- on error: no parameters.
|
|
|
|
+node.fs.cat(filename, encoding="utf8")+::
|
|
|
|
Outputs the entire contents of a file. Example:
|
|
+
|
|
--------------------------------
|
|
node.fs.cat("/etc/passwd").addCallback(function (content) {
|
|
puts(content);
|
|
});
|
|
--------------------------------
|
|
+
|
|
- on success: returns +data+, what was read from the file.
|
|
- on error: no parameters.
|
|
|
|
==== +node.fs.Stats+
|
|
|
|
Objects returned from +node.fs.stat()+ are of this type.
|
|
|
|
+stats.isFile()+::
|
|
|
|
+stats.isDirectory()+::
|
|
|
|
+stats.isBlockDevice()+::
|
|
|
|
+stats.isCharacterDevice()+::
|
|
|
|
+stats.isSymbolicLink()+::
|
|
|
|
+stats.isFIFO()+::
|
|
|
|
+stats.isSocket()+:: ...
|
|
|
|
|
|
|
|
=== HTTP
|
|
|
|
To use the HTTP server and client one must +require("/http.js")+ or
|
|
+include("/http.js")+.
|
|
|
|
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.
|
|
|
|
|
|
==== +http.Server+
|
|
|
|
[cols="1,2,10",options="header"]
|
|
|=========================================================
|
|
|Event | Parameters | Notes
|
|
|
|
|+"request"+ | +request, response+ | +request+ is an instance of +http.ServerRequest+
|
|
+
|
|
+response+ is an instance of +http.ServerResponse+
|
|
|
|
|+"connection"+ | +connection+ | When a new TCP connection is established.
|
|
+connection+ is an object of type
|
|
+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.
|
|
|
|
|=========================================================
|
|
|
|
+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 +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.
|
|
|
|
|
|
|
|
==== +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 a String. The
|
|
body encoding is set with
|
|
+request.setBodyEncoding()+.
|
|
|
|
|+"complete"+ | (none) | 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: text/plain\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.
|
|
+
|
|
Here is what's available: +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 +"binary"+. Defaults
|
|
to +"binary"+.
|
|
|
|
|
|
+request.pause()+ ::
|
|
Pauses request from emitting events. Useful to throttle back an upload.
|
|
|
|
|
|
+request.resume()+ ::
|
|
Resumes a paused request.
|
|
|
|
|
|
+request.connection+ ::
|
|
The +http.Connection+ object.
|
|
|
|
|
|
==== +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.
|
|
+
|
|
The first time +sendBody+ is called, it will send the buffered header
|
|
information and the first body to the client. The second time
|
|
+sendBody+ is called, Node assumes you're going to be streaming data, and
|
|
sends that seperately. That is, the response is buffered up to the
|
|
first chunk of body.
|
|
|
|
|
|
+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.
|
|
|
|
|
|
|
|
==== +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 = 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);
|
|
});
|
|
});
|
|
----------------------------------------
|
|
|
|
+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 +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()+.)
|
|
|
|
|
|
==== +http.ClientRequest+
|
|
|
|
This object is created internally and returned from the request methods of a
|
|
+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 +http.ClientResponse+.
|
|
|=========================================================
|
|
|
|
|
|
+request.sendBody(chunk, encoding="ascii")+ ::
|
|
|
|
Sends a chunk 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(responseListener)+ ::
|
|
|
|
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 +responseListener+ is a callback which
|
|
will be executed when the response headers have been received.
|
|
The +responseListener+ callback is executed with one
|
|
argument which is an instance of +http.ClientResponse+.
|
|
+
|
|
In the +responseListener+ callback, one can add more listeners to the
|
|
response, in particular listening for the +"body"+ event. Note that
|
|
the +responseListener+ is called before any part of the body is receieved,
|
|
so there is no need to worry about racing to catch the first part of the
|
|
body. As long as a listener for +"body"+ is added during the
|
|
+responseListener+ callback, the entire body will be caught.
|
|
+
|
|
----------------------------------------
|
|
// Good
|
|
request.finish(function (response) {
|
|
response.addListener("body", function (chunk) {
|
|
puts("BODY: " + chunk);
|
|
});
|
|
});
|
|
|
|
// Bad - misses all or part of the body
|
|
request.finish(function (response) {
|
|
setTimeout(function () {
|
|
response.addListener("body", function (chunk) {
|
|
puts("BODY: " + chunk);
|
|
});
|
|
}, 10);
|
|
});
|
|
----------------------------------------
|
|
|
|
|
|
|
|
|
|
==== +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 a String. 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 +"binary"+.
|
|
Defaults to +"binary"+.
|
|
|
|
+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 +http.Client+ that this response belongs to.
|
|
|
|
|
|
|
|
=== TCP
|
|
|
|
To use the TCP server and client one must +require("/tcp.js")+ or
|
|
+include("/tcp.js")+.
|
|
|
|
==== +tcp.Server+
|
|
|
|
Here is an example of a echo server which listens for connections
|
|
on port 7000
|
|
|
|
----------------------------------------
|
|
include("/tcp.js");
|
|
var server = createServer(function (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();
|
|
});
|
|
});
|
|
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 +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 occurred +errorno+ will be 0.
|
|
|=========================================================
|
|
|
|
+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=128)+ ::
|
|
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 128. 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.
|
|
|
|
|
|
==== +tcp.Connection+
|
|
|
|
This object is used as a TCP client and also as a server-side
|
|
socket for +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. +data+ will be a string.
|
|
Encoding of data is set by
|
|
+connection.setEncoding()+.
|
|
|+"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.)
|
|
|=========================================================
|
|
|
|
+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 +"ascii"+, +"utf8"+, or +"binary"+) for data that is received.
|
|
|
|
+connection.send(data, encoding="ascii")+::
|
|
Sends data on the connection. 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., it 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 inactivity on
|
|
the connection. By default all +tcp.Connection+ objects have a timeout
|
|
of 60 seconds (60000 ms).
|
|
+
|
|
If +timeout+ is 0, then the idle timeout is disabled.
|
|
|
|
+connection.setNoDelay(noDelay=true)+::
|
|
Disables the Nagle algorithm. By default TCP connections use the Nagle
|
|
algorithm, they buffer data before sending it off. Setting +noDelay+ will
|
|
immediately fire off data each time +connection.send()+ is called.
|
|
|
|
=== 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.
|
|
|
|
|
|
|
|
== REPL
|
|
|
|
A Read-Eval-Print-Loop is available both as a standalone program and easily
|
|
includable in other programs.
|
|
|
|
The standalone REPL is called +node-repl+ and is installed at
|
|
+$PREFIX/bin/node-repl+. It's recommended to use it with the program
|
|
+rlwrap+ for a better user interface. I set
|
|
------------------------------------
|
|
alias node-repl="rlwrap node-repl"
|
|
------------------------------------
|
|
in my zsh configuration.
|
|
|
|
Inside the REPL, Control+D will exit. The special variable +_+ (underscore) contains the
|
|
result of the last expression.
|
|
|
|
The library is called +/repl.js+ and it can be used like this:
|
|
------------------------------------
|
|
include("/utils.js");
|
|
include("/tcp.js");
|
|
nconnections = 0;
|
|
createServer(function (c) {
|
|
error("Connection!");
|
|
nconnections += 1;
|
|
c.close();
|
|
}).listen(5000);
|
|
require("/repl.js").start("simple tcp server> ");
|
|
------------------------------------
|
|
|
|
|
|
|
|
== 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:
|