NHttpLib is a NewtonScript unit for making HTTP connections. It can be used on any NIE 2.0 capable Newton device.
The package NHttpLib.pkg
contains the unit %NHttpLib:40Hz%
that exports one proto named protoNHttpLib
. This is the declaration which needs to be in for project using NHttpLib (the major version number in the DeclareUnit statement must match the major version number of the installed NHttpLib version):
DeclareUnit ('%NHttpLib:40Hz%, 3, 1,
{
protoNHttpLib: 0,
protoHNttpLibTransport: 1
}
);
Code using this proto looks like this:
httpLib := {
_proto: UR ('%NHttpLib:40Hz%, 'protoNHttpLib);
}
httpLib:MGet ("www.apple.com", 80, "/index.html");
Note: When fetching an URL, the opening of the Connection Slip before making a connection can be suppressed by setting fOpenConnectionSlip
to nil.
This code however would not do anything with the incoming data. It is also important to know that NHttpLib ‘‘does not’’ store the incoming data! To handle the different possible content types, the array fBodyInputSpecs
in the frame above needs to be set. An element of this array has the form
{
contentTypes: ...
spec: ...
}
where the contentTypes slot is an array of strings representing the handled content type like “text/html” or “text/xml” as returned by the HTTP server. It is also possible to specify “*” as a wildcard for any content type. The spec frame is an inputSpec that describes how to receive the data. A simple example that just prints out incoming HTML or XML data looks like this:
httpLib.fBodyInputSpecs := [
{
contentTypes: ["text/html", "text/xml"],
spec: {
async: true,
reqTimeout: 30000,
form: 'string,
termination: {
endSequence: ">"
},
inputScript: func (ep, data, terminator, options) begin
print (data);
end,
}
}];
Basically, an application should just have to implement the form
, termination
and inputScript
slots of the inputSpec.
To handle the successful termination of a transmission, it is also possible to specify the MConnectionClosed
function which gets called after the HTTP connection has been closed:
httpLib.MConnectionClosed := func () print ("Finished");
Before the body of the HTTP request is processed, the HTTP header fields are already available in the FSM frame. They can be accessed through the fHeaders
array. It contains elements with two slots, namely name
for the name of the header field and value
for its value. The content type and length can also be accessed through the slots fContentType
and fContentLength
. The HTTP return code is available in the slot fHTTPResult
. To perform additional actions before the body of the HTTP request is recevied, the MHeadersComplete
function can be specified:
httpLib.MHeadersComplete := func () begin
print ("Got all headers, body follows");
return true;
end;
The return value of the MHeadersCompleteFunction
determines if the download shall continue. To abort transmission after receiving the headers, nil
has to be returned.
The NHttpLib unit installs a new settings editor in the ‘‘Internet Setup’’ application. It can be used to add an HTTP proxy to an internet setup. The format of the proxy setting string can be any valid url, e.g. “192.168.1.1:8000”.
Cookies are stored in the soup “NHttpLib Cookies” if fStoreCookies is set to true in the base frame. Cookies are sent if fSendCookies is set to true. By default, cookie saving and sending is enabled.
NHttpLib adds a simple transport to the Inbox that allows downloading of URLs into the Inbox. After installing NHttpLib, a new menu item “Fetch URL” is added to the “Receive” picker in the Inbox. NHttpLib saves the downloaded data in the Inbox soup with this format:
item := {
...
body: {
data: <received data in a VBO, class 'binary>,
class: Intern (<content type of the data>)
}
...
}
This feature can be used for example by IC/VC or MAD Max to download MP3 files and import them into MAD Max or to fetch iCalendar data and import it later via IC/VC.
Version 2.0 is a complete rewrite of the library. It is a simpler design than the previous versions which were based on protoFSM. This version explicitly hard-codes the steps needed to grab a link, bind and connect an endpoint, transfer data and close the connection. It is implemented as a proto and should be assigned to a _proto slot in a frame.
Thanks to Ken Hagler, Grant Hutchinson, Patrick Clark, Frank Gruendel and Marcus Schneider for testing!
Cancelling operations via the Stop button in the status view seems cause instabilties at some times (timeouts are working better). Closing a connection is slow.
Setting the fEndpointEncoding to a value different from nil causes problems (the kPCRomanEncoding is not implemented on US MessagePads).