From a3d77ee4e7662a0ccc2d9989359c441e680955c8 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 30 Jun 2009 13:27:25 +0200 Subject: [PATCH] Add new documentation (using asciidoc!) --- configure | 13 +- website/api.html | 1101 ------------------------------------------------------ website/api.txt | 1009 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1018 insertions(+), 1105 deletions(-) delete mode 100644 website/api.html create mode 100644 website/api.txt diff --git a/configure b/configure index a3a2ed6..a5865ab 100755 --- a/configure +++ b/configure @@ -96,13 +96,18 @@ uninstall: test: all python tools/test.py --mode=release - -test-debug: all - python tools/test.py --mode=debug test-all: all python tools/test.py --mode=debug,release +website: website/api.html website/index.html + +website/api.html: website/api.txt + asciidoc -a toc -o website/api.html website/api.txt + +website-upload: website + scp website/* linode:~/tinyclouds/node/ + clean: @$WAF clean @@ -118,7 +123,7 @@ check: dist: @$WAF dist -.PHONY: clean dist distclean check uninstall install all test +.PHONY: clean dist distclean check uninstall install all test test-all website website-upload EOF } diff --git a/website/api.html b/website/api.html deleted file mode 100644 index 4b059e4..0000000 --- a/website/api.html +++ /dev/null @@ -1,1101 +0,0 @@ - - - - - - - - - - node.js - - -
-
    -
  1. Timers
  2. -
  3. Processes
  4. -
  5. - File I/O -
      -
    1. Wrappers
    2. -
    3. File
    4. -
    -
  6. -
  7. - TCP -
      -
    1. Server
    2. -
    3. Connection
    4. -
    -
  8. -
  9. - HTTP -
      -
    1. - Server -
        -
      1. Request
      2. -
      3. Response
      4. -
      -
    2. -
    3. - Client -
        -
      1. Request
      2. -
      3. Response
      4. -
      -
    4. -
    -
  10. -
  11. Modules -
      -
    1. onLoad
    2. -
    3. onExit
    4. -
    -
-
- -
-

Node API

-

- Conventions: Callbacks are object members which are prefixed with - on. All methods and members are camel cased. Constructors - always have a capital first letter. -

- -

- 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 - - V8 supports Blob objects - . -

- -

The following are global functions:

- -
-
puts(string, callback)
-
- Alias for stdout.puts(). Outputs the - string and a trailing new-line to - stdout. - -

- The callback argument is optional and mostly - useless: it will notify the user when the operation has - completed. 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. -

-
- -
print(string, callback)
-
Like puts() but without the trailing new-line.
- -
node.debug(string)
-
- A synchronous output function. Will block the process and - output the string immediately to stdout. Use with care. -
- -
node.exit(code)
-
Immediately ends the process with the specified code.
- -
ARGV
-
An array containing the command line arguments.
- -
stdout, - stderr, and - stdin -
-
Objects of type node.fs.File. (See below)
-
- -

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.
-
- -

Processes and IPC

- -

- Node provides a tridirectional popen(3) facility. - It is possible to stream data through the child's stdin, - stdout, and stderr in a fully non-blocking - way. -

- -
-
new node.Process(command)
-
Launches a new process with the given command. For example: -
var ls = new Process("ls -lh /usr");
-
- -
process.pid
-
The PID of the child process.
- -
process.onOutput = function (chunk) { };
-
A callback to receive output from the process's stdout. - At the moment the received data is always a string and utf8 encoded. - (More encodings will be supported in the future.) - -

If the process closes its stdout, this callback will - be issued with null as an argument. Be prepared for this - possibility. -

- -
process.onError = function (chunk) { };
-
A callback to receive output from the process's stderr. - At the moment the received data is always a string and utf8 encoded. - (More encodings will be supported in the future.) - -

If the process closes its stderr, this callback will - be issued with null as an argument. Be prepared for this - possibility. -

- -
process.onExit = function (exit_code) { };
-
A callback which is called when the child process terminates. - The argument is the exit status of the child. -
- -
process.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". -
- -
process.close();
-
Closes the process's stdin stream.
- -
process.kill(signal=node.SIGTERM);
-
Kills the child process with the given signal. If no argument is - given, the process will be sent node.SIGTERM. The standard - POSIX signals are defined under the node namespace (e.g. - node.SIGINT, node.SIGUSR1). -
-
- -

node.fs

- -

- File I/O is tricky because there are not simple non-blocking ways - to do it. Node handles file I/O by employing - - an internal thread pool - to execute file system calls. -

- -

- This part of the API is split into two parts: simple wrappers - around standard POSIX file I/O functions and a user-friendly - File object. -

- -

POSIX Wrappers

- -

- All POSIX wrappers have a similar form. They return - undefined and have a callback called - on_completion as their last argument. The - on_completion callback may be passed many parameters, - but the first parameter is always an integer indicating the error - status. If the status integer is zero, then the call was successful. - Example: -

-
-node.fs.unlink("/tmp/hello", function (status) {
-  if (status == 0) 
-    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", function (status, stats) {
-  puts("stats: " + JSON.stringify(stats));
-});
-

- because it could be that stat() is executed before - the rename(). The correct way to do this, is use the - on_completion callback for rename() -

-
-node.fs.rename("/tmp/hello", "/tmp/world", function (status) {
-  if (status != 0) return;
-  node.fs.stat("/tmp/world", function (status, stats) {
-    puts("stats: " + JSON.stringify(stats));
-  });
-});
- -
-
node.fs.rename(path1, path2, on_completion(status))
-
rename(2)
- -
node.fs.stat(path, on_completion(status, stats))
-
stat(2)
- -
node.fs.unlink(path, on_completion(status))
-
unlink(2)
- -
node.fs.rmdir(path, on_completion(status))
-
rmdir(2)
- -
node.fs.close(fd, on_completion(status))
-
close(2)
- -
node.fs.open(path, flags, mode, on_completion(status, fd))
-
- open(2) -

- The constants like O_CREAT are defined at - node.O_CREAT. -

-
- -
node.fs.write(fd, data, position, on_completion(status, written))
-
- Write data to the file specified by fd. -

- data is either an array of integer (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 - null, the data will be written at the current - position. -

-

See also - pwrite(2) -

-
- -
node.fs.read(fd, length, position, encoding, on_completion(status, data))
-
- 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. -

-
-
- -

node.fs.File

- -

Easy buffered file object.

- -

- Internal request queues exist for each file object so that - multiple commands can be issued at once without worry that they - will be executed out-of-order. Thus the following is safe: -

- -
-var file = new node.fs.File();
-file.open("/tmp/blah", "w+");
-file.write("hello");
-file.write("world");
-file.close();
- -

- Request queues are local to a single file. If one does -

-
-fileA.write("hello");
-fileB.write("world");
-

- it could be that fileB gets written to before - fileA is written to. If a certain operation order - is needed involving multiple files, use the completion callbacks: -

-
-fileA.write("hello", function () {
-  fileB.write("world");
-});
- -
-
new node.fs.File(options={})
-
- Creates a new file object. - -

- The options argument is optional. It can contain - the following fields -

-
    -
  • fd — a file descriptor for the file.
  • -
  • - encoding — how file.read() - should return data. Either "raw" or - "utf8". Defaults to raw. -
  • -
-
- -
file.onError = function (method, errno, msg) { }
-
- Callback. This is called internally anytime an error occurs with - this file. There are three arguments: the method name, the POSIX - errno, and a string describing the error. - -

Example

-
-var path = "/some/path/that/doesnt/exist";
-var file = new node.fs.File();
-file.onError = function (method, errno, msg) {
-  stderr.puts("An error occurred calling " + method);
-  stderr.puts(msg);
-  node.exit(1);
-}
-file.open(path, "w+")
-
- -
file.open(path, mode, on_completion())
-
- Opens the file at path. -

- mode is a string: "r" open for - reading and writing. "r+" open for only reading. - "w" create a new file for reading and writing; - if it already exists truncate it. "w+" create a - new file for writing only; if it already exists truncate it. - "a" create a new file for writing and reading. - Writes append to the end of the file. - - "a+" - -

-

- The on_completion is a callback that is made - without arguments when the operation completes. It is optional. - If an error occurred the on_completion callback - will not be called, but the file.onError will be - called. -

-
- -
file.read(length, position, on_completion(data))
-
- -
file.write(data, position, on_completion(written))
-
- -
file.close(on_completion())
-
-
- -

node.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.onConnect = function () {
-    socket.send("hello\r\n");
-  };
-  socket.onReceive = function (data) {
-    socket.send(data);
-  };
-  socket.onEOF = function () {
-    socket.send("goodbye\r\n");
-    socket.close();
-  };
-}
-var server = new node.tcp.Server(Echo, {backlog: 1024});
-server.listen(7000, "localhost");
- -
-
new node.tcp.Server(connection_handler(socket), options={});
-
- Creates a new TCP server. - -

- connection_handler is a callback which is called - on each connection. It is given one argument: an instance of - node.tcp.Connection. -

- -

- options for now only supports one option: - backlog which should be an integer and describes - how large of a connection backlog the operating system should - maintain for this server. The backlog defaults - to 1024. -

-
- -
server.listen(port, host=null)
-
- Tells the server to listen for TCP connections to port - and host. Note, host is optional. If - host is not specified the server will accept - connections to any IP address on the specified port. -
- -
server.close()
-
Stops the server from accepting new connections.
-
- -

node.tcp.Connection

- -

- This object is used as a TCP client and also as a server-side - socket for node.tcp.Servers. -

- -
-
new node.tcp.Connection()
-
Creates a new connection object.
- -
connection.connect(port, host="127.0.0.1")
-
- Opens a connection to the specified port and - host. If the second parameter is omitted, localhost is - assumed. -
- -
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.fullClose()
-
- Close both ends of the connection. Data that is received - after this call is responded to with RST packets. If you don't - know about this, just use close(). -
- -
connection.forceClose()
-
- Ensures that no more I/O activity happens on this socket. Only - necessary in case of errors (parse error or so). -
- -
connection.onConnect = function () { };
-
Call once the connection is established.
- -
connection.onReceive = function (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. -
- -
connection.onEOF = function () { };
-
- Called when the other end of the connection sends a FIN packet. - onReceive will not be called after this. After - receiving this readyState will be - "writeOnly". You should probably just call - connection.close() in this callback. -
- -
connection.onDisconnect = function (had_error) { };
-
- Called once the connection is fully disconnected. - -

- The callback is passed one boolean argument had_error. - This lets one know if the connect was closed due to an error. - (TODO: look up error codes.) -

-
- -
connection.onError = function () { };
-
Called on an error.
-
- -

node.http

- -

- The HTTP interfaces here are designed to support many features - of the protocol which have been traditionally difficult to handle. - In particular, large, possibly chunked, 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 array of 2-element - arrays like this -

-
-[ ["Content-Length", "123"]
-, ["Content-Type", "text/plain"]
-, ["Connection", "keep-alive"]
-, ["Accept", "*/*"]
-]
-

- Dictionary-like objects are popularly used to represent HTTP - headers but they are an incorrect abstraction. It is rare, but - possible, to have multiple header lines with the same field. - Setting multiple cookies in a single response, for example, can - only be done with multiple Cookie lines. -

- -

- Node's HTTP abstraction deals with connection handling and message - parsing only. It parses the message into headers and body - but it does - not parse any of the headers or the body. This is left to the user. That - means, for example, that Node does not (and will never) provide API - to access or manipulate Cookies or multi-part bodies. -

- -

node.http.Server

- -
-
new node.http.Server(request_handler, options);
-
-

Creates a new web server.

- -

- The options argument is optional. The - options argument accepts the same values as the - options argument for node.tcp.Server does. -

- -

- The request_handler is a callback which is made - on each request with a ServerRequest and - ServerResponse arguments. -

-
- -
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. -

-
- -
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. It is passed to the user as the first argument to the - request_handler callback. -

- -
-
req.method
-
The request method as a string. Read only. Example: - "GET", "DELETE". -
- -
req.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 req.uri will be -
-{ path: "/status", 
-  file: "status", 
-  directory: "/", 
-  params: { "name" : "ryan" } 
-}
- In particular, note that req.uri.protocol is - undefined. This is because there was no URI protocol given - in the actual HTTP Request. -
- -
req.uri.anchor
-
req.uri.query
-
req.uri.file
-
req.uri.directory
-
req.uri.path
-
req.uri.relative
-
req.uri.port
-
req.uri.host
-
req.uri.password
-
req.uri.user
-
req.uri.authority
-
req.uri.protocol
-
req.uri.params
-
req.uri.toString(), req.uri.source
- -
req.headers
-
- The request headers expressed as an array of 2-element arrays. - Read only. -
- -
req.httpVersion
-
- The HTTP protocol version as a string. Read only. Examples: - "1.1", "1.0" -
- -
req.onBody = function (chunk) { };
-
- Callback. Should be set by the user to be informed of when a - piece of the message body is received. Example: -
-req.onBody = function (chunk) {
-  puts("part of the body: " + chunk);
-};
- 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 req.setBodyEncoding(). -

-
- -
req.onBodyComplete = function () { };
-
- Callback. Made exactly once for each message. No arguments. - After onBodyComplete is executed - onBody will no longer be called. -
- -
req.setBodyEncoding(encoding)
-
- Set the encoding for the request body. Either "utf8" - or "raw". Defaults to raw. -
- -
req.interrupt()
-
- Interrupt the request. You will not receive anymore callbacks. - This is useful if, for example someone is streaming up a file but it - is too large and neesd to be stopped. The connection to the client - will be closed immediately. -
-
- -

node.http.ServerResponse

- -

- This object is created internally by a HTTP server—not by - the user. It is passed to the user as the second argument to the - request_handler callback. -

- -
-
res.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, should be an array of 2-element - arrays, representing the response headers. - -

Example:

-
-var body = "hello world";
-res.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 res.finish() is called. -

-
- -
res.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. -

-
- -
res.finish()
-
- This method signals that all of the response headers and body - has been sent; that server should consider this message complete. - The method, res.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 = new node.http.Client(80, "google.com");
-var req = google.get("/");
-req.finish(function (res) {
-  puts("STATUS: " + res.statusCode);
-  puts("HEADERS: " + JSON.stringify(res.headers));
-  res.setBodyEncoding("utf8");
-  res.onBody = function (chunk) {
-    puts("BODY: " + chunk);
-  };
-});
- -
-
new node.http.Client(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. - -

- request_headers is optional. - request_headers should be an array of 2-element - arrays. 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. -

- -

- Important: the request is not complete. This method only sends - the header of the request. One needs to call - req.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 - req.sendBody().) -

- -

- GET and HEAD requests normally are - without bodies but HTTP does not forbid it, so neither do we. -

-
-
- -

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. -

- -
-
req.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. -

-
-
req.finish(response_handler)
-
- 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_handler is a user-supplied - callback which will be executed exactly once when the server - response headers have been received. The - response_handler callback is executed with one - argument: a ClientResponse object. -

-
-
- -

node.http.ClientResponse

- -

- This object is created internally and passed to the - response_handler callback (is given to the client in - req.finish function). The response object appears - exactly as the header is completely received but before any part - of the response body has been read. -

- -
-
res.statusCode
-
The 3-digit HTTP response status code. E.G. 404.
- -
res.httpVersion
-
- The HTTP version of the connected-to server. Probably either - "1.1" or "1.0". -
- -
res.headers
-
The response headers. An Array of 2-element arrays.
- -
res.onBody
-
- Callback. Should be set by the user to be informed of when a - piece of the response body is received. A chunk of the body is - given as the single argument. The transfer-encoding has been - removed. - -

- 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 res.setBodyEncoding(). -

-
- -
res.onBodyComplete
-
- Callback. Made exactly once for each message. No arguments. - After onBodyComplete is executed - onBody will no longer be called. -
- -
res.setBodyEncoding(encoding)
-
- Set the encoding for the response body. Either - "utf8" or "raw". Defaults to raw. -
-
- -

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 mjsunit.js. -

- -

The contents of foo.js:

- -
-include("mjsunit.js");
-function onLoad () {
-  assertEquals(1, 2);
-}
-

The contents of mjsunit.js:

- -
-function fail (expected, found, name_opt) {
-  // ...
-}
-function deepEquals (a, b) {
-  // ...
-}
-exports.assertEquals = function (expected, found, name_opt) {
-  if (!deepEquals(found, expected)) {
-    fail(expected, found, name_opt);
-  }
-};
- -

- The module mjsunit.js has exported a function - assertEquals(). mjsunit.js must be - in the same directory as foo.js for - include() to find it. The module path is relative - to the file calling include(). -

- -

Alternatively one can use HTTP URLs to load modules. For example, - -

include("http://tinyclouds.org/node/mjsunit.js");
- -

- include() inserts the exported objects from the - specified module into the global namespace. -

- -

onLoad

- -

- Because module loading does not happen instantaneously, and - because Node has a policy of never blocking, a callback - onLoad can be set that will notify the user when the - included modules are loaded. Each file/module can have an - onLoad callback. -

- -

- To export an object, add to the special exports - object. - The functions fail and - deepEquals are not exported and remain private to - the module. - - Alternatively, one can use this instead of - exports. -

- -

- require() is like include() except - does not polute the global namespace. It returns a namespace - object. The exported objects can only be guaranteed to exist - after the onLoad() callback is made. For example: -

-
-var mjsunit = require("mjsunit.js");
-function onLoad () {
-  mjsunit.assertEquals(1, 2);
-}
- -

- include() and require() cannot be - used after onLoad() is called. -

- -

onExit

- -

- When the program exits a callback onExit() will be - called for each module (children first). -

- -

- The onExit() callback cannot perform I/O as the process is - going to forcably exit in several microseconds, however it is a good - hook to perform some constant time checks of the module's state. - It's useful for unit tests. -

- -
-include("mjsunit.js");
-
-var timer_executed = false;
-
-setTimeout(function () {
-  timer_executed = true
-}, 1000);
-
-function onExit () {
-  assertTrue(timer_executed);
-}
-
- -

- Just to reiterate: onExit(), is not the place to close - files or shutdown servers. The process will exit before they get - performed. -

- -
- - diff --git a/website/api.txt b/website/api.txt new file mode 100644 index 0000000..7ca8c61 --- /dev/null +++ b/website/api.txt @@ -0,0 +1,1009 @@ +NODE(1) +======= +Ryan Dahl +Version, 0.1.0, 2009.06.28 + + +== NAME + +node - purely event-based 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/ +---------------------------------------- + + +== DESCRIPTION + +Node provides an easy way to build scalable network programs. In the above +example, the 2 second delay does not prevent the server from handling new +requests. Node tells the operating system (through +epoll+, +kqueue+, ++/dev/poll+, or +select+) that it should be notified when the 2 seconds are +up or if a new connection is made--then it goes to sleep. If someone new +connects, then it executes the callback, if the timeout expires, it executes +the inner callback. Each connection is only a small heap allocation. + +This is in contrast to today's more common model where OS threads are employed +for concurrency. Thread-based networking +http://www.sics.se/~joe/apachevsyaws.html[is] +http://www.kegel.com/c10k.html[relatively] +http://bulk.fefe.de/scalable-networking.pdf[inefficient] +and very difficult to use. Node will show much better memory efficiency +under high-loads than systems which allocate 2mb thread stacks for each +connection. Furthermore, users of Node are free from worries of +dead-locking the process--there are no locks. In fact, no function in Node +directly performs I/O. Because nothing blocks, less-than-expert programmers +are able to develop fast systems. + +Node is similar in design to systems like Ruby's +http://rubyeventmachine.com/[Event Machine] +or Python's http://twistedmatrix.com/[Twisted]. +Node takes the event model a bit further. For example, in other systems there +is always a blocking call to start the event-loop. Typically one defines +behavior through callbacks at the beginning of a script and at the end starts a +server through a call like +EventMachine::run()+. In Node it works differently. +By default Node enters the event loop after executing the input script. Node +exits the event loop when there are no more callbacks to perform. Like in +traditional browser javascript, the event loop is hidden from the user. + +Node's HTTP API has grown out of my difficulties developing and working with +web servers. For example, streaming data through most web frameworks is +impossible. Or the oft-made false assumption that all message headers have +unique fields. Node attempts to correct these and other problems in its API. +Coupled with Node's purely evented infrastructure, it will make a more +comprehensive foundation for future web libraries/frameworks. + +_But what about multiple-processor concurrency? Threads are necessary to scale +programs to multi-core computers._ The name _Node_ should give some hint at how +it is envisioned being used. Processes are necessary to scale to multi-core +computers, not memory-sharing threads. The fundamentals of scalable systems are +fast networking and non-blocking design--the rest is message passing. In the +future, I'd like Node to be able to spawn new processes (probably using the +http://www.whatwg.org/specs/web-workers/current-work/[Web Workers API]), +but this is something that fits well into the current design. + + + +== API + +Callbacks are object members which are prefixed with ++on+. All methods and members are camel cased. Constructors +always have a capital first letter. + +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)+:: +Alias for +stdout.puts()+. 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. + + + +=== Global Variables + + + ++ARGV+ :: +An array containing the command line arguments. + + ++stdout+, +stderr+, and +stdin+ :: +Objects of type +node.fs.File+. (See below.) + ++__filename+ :: +The filename of the script being executed. + + + +=== 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+ + ++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. + ++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. + + + + +=== 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"); +function onLoad () { + 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"); +function onLoad () { + puts("The area of a cirlce of radius 4 is " + area(4)); +} +---------------------------------------- + + +==== +onLoad()+ + +Because module loading does not happen instantaneously and because Node has +a policy of never blocking, a callback +onLoad+ can be set that will notify +the user when the included modules are loaded. Each file/module can have +its own +onLoad+ callback. + ++include()+ and +require()+ cannot be used after +onLoad()+ is called. + + +==== +onExit()+ + +When the program exits a callback +onExit()+ will be called for each module +(children first). + +The +onExit()+ callback 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); + +function onExit () { + assertTrue(timer_executed); +} +---------------------------------------- + +Just to reiterate: +onExit()+, 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.Process+. It is possible to stream data through the child's +stdin+, ++stdout+, and +stderr+ in a fully non-blocking way. + +==== +node.Process+ + +.Events +[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. + +|========================================================= + ++new node.Process(command)+:: +Launches a new process with the given +command+. For example: ++ +---------------------------------------- +var ls = new node.Process("ls -lh /usr"); +ls.addListener("output", function (data) { + puts(data); +}); +---------------------------------------- + + ++process.pid+ :: +The PID of the child process. + + ++process.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"+. + + ++process.close()+ :: +Closes the process's +stdin+ stream. + + ++process.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 + +This part of the API is split into two parts: simple wrappers +around standard POSIX file I/O functions and a user-friendly ++File+ object. + +==== POSIX Wrappers + +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)); + }); + }); +---------------------------------------- + + ++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.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+, what was read from the file. +- on error: no parameters. + + +==== +node.fs.File+ + +A buffered file object. + +Internal request queues exist for each instance of +node.fs.File+ so that +multiple commands can be issued at once. Thus the following is safe: + +---------------------------------------- +var file = new node.fs.File(); +file.open("/tmp/blah", "w+"); +file.write("hello"); +file.write("world"); +file.close(); +---------------------------------------- + +[cols="1,2,10",options="header"] +|========================================================= +|Event |Parameters | Notes +|+"error"+ | | Emitted if an error happens. +|========================================================= + ++new node.fs.File(options={})+:: +Creates a new file object. ++ +The +options+ argument is optional. It can contain +the following fields ++ +- +fd+: a file descriptor for the file. +- +encoding+: how +file.read()+ should return data. Either +"raw"+ or +"utf8"+. +Defaults to +"raw"+. + + ++file.open(path, mode)+:: +Opens the file at +path+. ++ ++mode+ is a string: ++ +- "r", open for reading and writing. +- "r+", open for only reading. +- "w", create a new file for reading and writing; if it already exists truncate it. +- "w+", create a new file for writing only; if it already exists truncate it. +- "a", create a new file for writing and reading. Writes append to the end of the file. +- "a+" + + ++file.read(length, position)+:: +Reads +length+ bytes from the file at +position+. +position+ can be omitted +to write at the current file position. + + ++file.write(data, position)+:: +Writes +data+ to the file. +position+ can be omitted to write at the current +file position. + + ++file.close()+:: +Closes the file. + + +=== 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 array of 2-element +arrays 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+. + +|========================================================= + ++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. + ++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+ :: +The request headers expressed as an array of 2-element arrays. +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.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+, should be an array +of 2-element arrays, representing 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. ++request_headers+ should be an array of 2-element +arrays. 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. An Array of 2-element arrays. + ++response.setBodyEncoding(encoding)+ :: + Set the encoding for the response body. Either +"utf8"+ or +"raw"+. + Defaults to raw. + + + +=== 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, {backlog: 1024}); +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+. +|========================================================= + ++node.tcp.createServer(connection_listener, options={});+ :: +Creates a new TCP server. ++ +The +connection_listener+ argument is automatically set as a listener for +the +"connection"+ event. ++ ++options+ for now only supports one option: ++backlog+ which should be an integer and describes +how large of a connection backlog the operating system should +maintain for this server. The +backlog+ defaults +to 1024. + + ++server.listen(port, host=null)+ :: +Tells the server to listen for TCP connections to +port+ +and +host+. Note, +host+ is optional. If ++host+ is not specified the server will accept +connections to any IP address on the specified port. + + ++server.close()+:: +Stops the server from accepting new connections. + + +==== +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. +|+"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. +|+"disconnect"+ | +had_error+ | Emitted once the connection is fully + disconnected. The argument +had_error+ + is a boolean which says if the connection + was closed due to a transmission error. + (TODO: access error codes.) +|========================================================= + ++new node.tcp.Connection()+:: + Creates a new connection object. + + ++connection.connect(port, host="127.0.0.1")+:: + Opens a connection to the specified +port+ and + +host+. If the second parameter is omitted, localhost is + assumed. + + ++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.fullClose()+:: +Close both ends of the connection. Data that is received +after this call is responded to with RST packets. If you don't +know about this, just use +close()+. + + ++connection.forceClose()+:: +Ensures that no more I/O activity happens on this socket. Only +necessary in case of errors (parse error or so). + + + + + +// vim: set syntax=asciidoc: -- 2.7.4