Skip to content
This repository has been archived by the owner on Oct 4, 2022. It is now read-only.
Michael Schwartz edited this page Jul 9, 2014 · 1 revision

http module

Decaf implements an HTTP module that provides both client and server functionality.

Client class

First you import the Client class into your name space.

var Client = require('http').Client;

From here, you create a client instance for the URL you want to access.

var client = new Client('http://google.com');

If you want to follow any redirects sent by the server:

client.setFollowRedirects(true);

Next you will call client.get() to perform the actual operation:

var result = client.get();
// result.status (200, 404, etc.)
// result.responseMessage (OK, Not Found, etc.)
// result.responseText (html of google's home page)

Being synchronous, all this is chainable, and there's no callbacks:

var result = new Client('http://google.com')
	.setFollowRedirects(true)
	.get();

Posting forms to a server is trivial as well. Instead of calling the client's get() method, you call the client's post() method. Post takes an Object/hash argument. The member names are the field names and the values are the values. So something like:

var result = new Client('http://api.myserver.com')
	.post({
		username: 'me',
		password: 'secret'
	});

Server class

The server implementation strongly resembles the base http server in NodeJS. In fact, the demo server on the NodeJS.org WWW site runs unmodified in Decaf.

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

Server instance

The http.createServer() method returns an instance of a Server object.

Server contains the following methods:

listen(port, bindAddress, numChildren)

This causes the server to listen on the specified port.

The bindAddress argument is an IP address on the host machine to listen on. It typically will be '127.0.0.1' (localhost) during development, but you may want to set it to '0.0.0.0' to listen on all interfaces on the host in production.

The numChildren argument is optional. The decaf http server is multithreaded. This argument specifies the number of request handler (Child) threads to pre-spawn. This limits the total number of simultaneous requests the server can handle to numChildren. The default is 50.

Note: 5000 numChildren consume about 400M of RAM on 64 bit Linux. This is equivalent to 1/4 of the RAM in a small instance on Amazon AWS.

webSocket(path, onConnect)

This method binds a WebSocket listener for the specified WebSocket URI/path. The onConnect method is called when a connection to the WebSocket is made. The onConnect method is called with a WebSocket object instance as its only argument.

The WebSocket is an evented interface. Yes, you can have evented interfaces in synchronous programming!

WebSocket interface

The WebSocket instance provides the following methods:

on(eventName, func)

Adds an event handler (func) for the specified eventName to this WebSocket instance.

There are only two predefined eventNames. The "message" event is triggered when a message is received on the WebSocket. The "close" event is triggered with the browser closes the connection. However, you may define your own event names and trigger those events as you see fit.

The function is called with whatever arguments are passed to fireEvent() - see below.

fireEvent(eventName, data)

Fires the specified event, calling all the event handler functions registered on this WebSocket, with data as the function arguments.

broadcast(path, message)

Send a message to each WebSocket instance with the specified URI/path.

The messages are sent in a separate thread so this method can return right away. There is no notification that all messages are sent or if any failed.

The req Object

The req object represents information about the request made by the browser. Note that modules added to your decaf application may add new members or alter existing members of this object.

Its base members are:

req.method

This is the request method. The value of this field will be something like 'GET' or 'POST' or 'HEAD'.

req.uri

This is the part of the requested URL, up to, but not including the query string or the host name.

If the URL is http://company.com/something?foo=10&bar=20, then the value of req.uri will be /something.

req.queryParams

This is a hash representing the query string part of the requested URL.

If the URL ends with ?foo=10&bar=20, then req.queryParams will be:

{ foo: 10, bar: 20 }

req.proto

This is the HTTP protocol requested by the browser. The value of this field will be something like 'HTTP/1.0' or 'HTTP/1.1'.

req.headers

This is a hash of the request headers sent by the browser. The keys in the hash are the request header names, lower cased. This makes it so you don't have to worry about some browsers sending "User-Agent" and others sending "User-agent."

Example:

{
	'accept-encoding': 'gzip,deflate,sdch','
	'accept-language': 'en-US,en;q=0.8','
	'cache-control': 'max-age=0','
	'connection': 'keep-alive','
	'host': 'localhost:8080','
	'referer': 'http://localhost:8080/api/MySQL',
	'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36'
}

req.host

This is the host part of the requested URL. For example, if the URL was http://company.com:8080/something?foo=10&bar=20 then the value of req.host will be company.com.

req.port

This is the port part of the requested URL. For example, if the URL was http://company.com:8080/something?foo=10&bar=20 then the value of req.host will be 8080.

If no :PORT is specified in the URL, then the value will be 80.

req.remote_addr

This is the IP address of the remote side of the connection, or in other words, the IP address of the user/browser connected to the server.

req.cookies

This is a hash of the cookies sent to the server. The index in the hash is the name of the cookie, and the value is the value of the cookie.

req.data

If the data posted to the server is type application/json, then req.data is the JSON that was posted, decoded (to JavaScript object).

If the post content-type is unrecognized, then req.data contains the raw value of the posted data.

Otherwise, req.data is a hash of all the query string variables, post variables, and cookies. They are all merged into this one object.

File Uploads

File uploads are in the req.data hash as well. An uploaded file's value is another hash that looks something like:

{
  "name" :  "upload",
  "filename" : "testx.gif",
  "contentType" : "image/gif",
  "content" : a java byte array containing the file content,
  "size" : 51593
}

The res Object

The res object represents information that is to be sent to the browser, or the response. Note that modules added to your decaf application may add new members or alter existing members of this object.

Its base members are:

res.status

This is the HTTP status to be sent to the client. Set this to a number like 200 for OK, 404 for not found, and so on.

Note that member functions of the res object may set this for you.

res.contentType

This is a string value for the Content-Type: response header to be sent. Set this to a value like "text/html" or "text/css", and so on.

Note that some member functions of the res object may set this for you.

res.headers

This is a hash of response headers to be sent to the client. You probably will only want to add your own custom headers, not mess with the ones that are part of the HTTP protocol (e.g. Content-Type, Content-Length, etc.).

For example:

res.headers['X-MY-CUSTOM-HEADER'] = 'my custom header value';

res.setCookie(key, value, expires, path, domain)

Call this method to set a cookie in the browser. The key and value are the only arguments required.

If expires is not present or is null, the cookie will exist until the user closes his browser. If expires is a Date instance, it will be used to set the expiry of the cookie. Otherwise, expires must be a valid GMT time string per the HTTP spec.

If path is not present or is null, the cookie's path will be set to /, otherwise it will be set to the value passed.

If domain is present, it will be set as the cookie's domain.

res.unsetCookie(key)

Call this method to remove a cookie in the browser. The key argument is the same value you called res.setCookie() with.

res.writeHead(status, headers)

Call this method to set the status and headers for your response. A typical invocation might look like:

res.writeHead(200, { 'Content-Type' : 'text/html' });

Note: this is compatible with NodeJS.

res.end(content, gzip)

Call this method to send text content to the browser.

If content is an array of strings, it will be sent joined with newlines. That is, content.join('\n).

If the gzip argument is set to true, then the response will be gzip compressed.

This method will add a Content-Encoding and Content-Length header to the response, and then sends the headers, then the content.

Effectively, calling this method ends the response. Once this method returns, your code may continue to execute, but should not try to send any more to the client via this res object.

This method is consistent with the NodeJS API.

res.send(status, body) or just res.send(body)

This method is inspired by res.send() of ExpressJS for NodeJS.

Rather than calling res.writeHead() and res.end() to send your response to the client, you may call this method instead.

If status is present, it will be the server response code (200 for OK, 404 for not found, etc.).

If body is a string, it is assumed to be HTML content and the response is properly sent as such. If body is an object, the object is sent as JSON to the client.

Example (Send HTML):

res.send('<html><head><title>hello</title></head><body>hello</body></html>');

Example (Send JSON):

res.send({ a: 10, b: 20 });

res.sendFile(filename, modifiedSince)

Send a file to the client. The mime type ("Content-Type" header) is determined from the filename's dot extension.

This is an alternative to sending a response using res.send() or res.writeHead() plus res.end(). Once you call this method, you shouldn't call any more methods of this instance.

If the optional modifiedSince argument is set to false, then the method's 304 handling logic will be disabled. If not present or not set to false, then 304 handling logic will be enabled.

With 304 logic enabled, the request headers are checked for if-modified-since and the time stamp on the file compared against it. If the file on disk is not newer, then a 304 status response is sent. This avoids sending files the browser already has in its cache.

All this 304 handling is done automatically for you so you don't have to worry about its implementaiton. You will rarely want to set modifiedSince to false.

res.sendBytes(bytes, mimeType, lastModified, modifiedSince)

This method sends a Java byte array (bytes argument) to the client. It's an alternative to calling res.sendFile() if you have already read in the file contents, or are sending an image you've manipulated with decaf's image methods, etc.

Since there is no filename involved, you must specifiy the mimeType.

If you want 304 logic enabled, you must specify the lastModified and modifiedSince arguments.

The lastModified parameter is the time stamp that the bytes should be considered as last modified. This value is in milliseconds, not a UNIX timestamp.

the modifiedSince parameter is the value from the request's if-modified-since header field. If this is a string, it will be parsed to a Date. Otherwise it must be an integer, millseconds time stamp.

res.redirect(uri)

This method generates a 303 redirect to the specified URL. The URL may be a relative one.

This method does NOT return.

res.stop()

End request processing.

This method simply does a throw 'RES.STOP' string. The http server module catches errors and handles the 'RES.STOP' string appropriately.

This method does NOT return.