MODULE NewHTTPClient;
IMPORT
Streams, WebHTTP, IP, DNS, TCP, Strings, Files, TFLog, Modules, KernelLog;
CONST
ErrIllegalURL* = -1;
ErrNotConnected* = -2;
ErrIllegalResponse* = -3;
TYPE
HTTPConnection* = OBJECT
VAR host, referer, useragent, accept : ARRAY 128 OF CHAR;
port : LONGINT;
http11 : BOOLEAN;
con : TCP.Connection;
requestHeader*: WebHTTP.RequestHeader;
responseHeader*: WebHTTP.ResponseHeader;
PROCEDURE &New*;
BEGIN
requestHeader.referer := "";
requestHeader.useragent := "BimBrowser (BimbOS 2004)";
END New;
PROCEDURE Open;
VAR
fadr: IP.Adr;
res : LONGINT;
BEGIN
IF (con # NIL) & (con.state = TCP.Established) THEN RETURN END;
DNS.HostByName(host, fadr, res);
IF res = DNS.Ok THEN
NEW(con); con.Open(TCP.NilPort, fadr, port, res);
IF res # TCP.Ok THEN con := NIL END
END
END Open;
PROCEDURE Close*;
BEGIN
IF con # NIL THEN con.Close; con := NIL END;
END Close;
PROCEDURE Get*(CONST url : ARRAY OF CHAR; http11 : BOOLEAN; VAR out : Streams.Reader; VAR res : LONGINT);
VAR w : Streams.Writer; r : Streams.Reader;
x : WebHTTP.AdditionalField;
host : ARRAY 128 OF CHAR;
path : ARRAY 2048 OF CHAR;
port : LONGINT;
dechunk: WebHTTP.ChunkedInStream;
lin : WebHTTP.LimitedInStream;
BEGIN
requestHeader.maj := 1;
IF http11 THEN requestHeader.min := 1 ELSE requestHeader.min := 0 END;
IF WebHTTP.SplitHTTPAdr(url, host, path, port) THEN
IF (host # SELF.host) OR (port # SELF.port) THEN Close END;
COPY(host, SELF.host);
SELF.port := port;
IF path = "" THEN path := "/" END;
Open;
IF con = NIL THEN res := ErrNotConnected; RETURN END;
Streams.OpenWriter(w, con.Send); Streams.OpenReader(r, con.Receive);
WebHTTP.WriteRequestLine(w, requestHeader.maj, requestHeader.min, WebHTTP.GetM, path, host);
IF requestHeader.referer # "" THEN w.String("Referer: "); w.String(requestHeader.referer); w.Ln() END;
IF requestHeader.useragent # "" THEN w.String("User-Agent: "); w.String(requestHeader.useragent); w.Ln() END;
IF requestHeader.accept # "" THEN w.String("Accept: "); w.String(requestHeader.accept); w.Ln() END;
x := requestHeader.additionalFields;
WHILE x # NIL DO
w.String(x.key); w.Char(" "); w.String(x.value);w.Ln();
x := x.next
END;
w.Ln(); w.Update();
WebHTTP.ParseReply(r, responseHeader, res, log);
IF (Strings.Pos("hunked", responseHeader.transferencoding) > 0) THEN NEW(dechunk, r, out)
ELSIF responseHeader.contentlength >= 0 THEN NEW(lin, r, out, responseHeader.contentlength)
ELSE out := r
END;
res := 0;
x := responseHeader.additionalFields;
WHILE x # NIL DO
x := x.next
END;
ELSE
res := ErrIllegalURL
END
END Get;
PROCEDURE Post*(CONST url : ARRAY OF CHAR; CONST headervars: ARRAY OF CHAR; MIME: ARRAY OF CHAR; body: Streams.Reader; length: LONGINT; VAR out : Streams.Reader; VAR res : LONGINT);
VAR w : Streams.Writer; r : Streams.Reader;
x : WebHTTP.AdditionalField;
host : ARRAY 128 OF CHAR;
path : ARRAY 2048 OF CHAR;
buf: ARRAY 1024 OF CHAR;
port : LONGINT;
dechunk: WebHTTP.ChunkedInStream;
lin : WebHTTP.LimitedInStream;
len: ARRAY 16 OF CHAR;
l:LONGINT;
BEGIN
requestHeader.maj := 1;
IF TRUE THEN requestHeader.min := 1 ELSE requestHeader.min := 0 END;
IF WebHTTP.SplitHTTPAdr(url, host, path, port) THEN
IF (host # SELF.host) OR (port # SELF.port) THEN Close END;
COPY(host, SELF.host);
SELF.port := port;
IF path = "" THEN path := "/" END;
IF Strings.Length(headervars)>0 THEN Strings.AppendChar(path,"?"); Strings.Append(path,headervars); END;
Open;
IF con = NIL THEN res := ErrNotConnected; RETURN END;
Streams.OpenWriter(w, con.Send); Streams.OpenReader(r, con.Receive);
WebHTTP.WriteRequestLine(w, requestHeader.maj, requestHeader.min, WebHTTP.PostM, path, host);
IF requestHeader.referer # "" THEN w.String("Referer: "); w.String(requestHeader.referer); w.Ln() END;
IF requestHeader.useragent # "" THEN w.String("User-Agent: "); w.String(requestHeader.useragent); w.Ln() END;
IF requestHeader.accept # "" THEN w.String("Accept: "); w.String(requestHeader.accept); w.Ln() END;
WebHTTP.SetAdditionalFieldValue(requestHeader.additionalFields,"Content-Type",MIME);
IF length>0 THEN
Strings.IntToStr(length,len);
WebHTTP.SetAdditionalFieldValue(requestHeader.additionalFields,"Content-Length", len);
ELSE HALT(300)
END;
x := requestHeader.additionalFields;
WHILE x # NIL DO
w.String(x.key); w.String(": "); w.String(x.value);w.Ln();
x := x.next
END;
w.Ln();
WHILE length>0 DO
body.Bytes(buf, 0, MIN(LEN(buf),length), l);
w.Bytes(buf,0,l);
DEC(length,l);
END;
w.Update();
WebHTTP.ParseReply(r, responseHeader, res, log);
IF (Strings.Pos("hunked", responseHeader.transferencoding) > 0) THEN NEW(dechunk, r, out)
ELSIF responseHeader.contentlength >= 0 THEN NEW(lin, r, out, responseHeader.contentlength)
ELSE out := r
END;
WebHTTP.LogResponseHeader(log, responseHeader);
res := 0;
x := responseHeader.additionalFields;
WHILE x # NIL DO
x := x.next
END;
ELSE
res := ErrIllegalURL
END
END Post;
END HTTPConnection;
VAR log : TFLog.Log;
PROCEDURE CleanUp;
BEGIN
log.Close
END CleanUp;
PROCEDURE Test*;
VAR h : HTTPConnection;
r : Streams.Reader;
res : LONGINT;
BEGIN
NEW(h);
h.Get("http://www.bimbodot.org", TRUE, r, res);
KernelLog.String("res= "); KernelLog.Int(res, 0); KernelLog.Ln;
WHILE r.res = 0 DO KernelLog.Char(r.Get()) END;
KernelLog.String("Loop finished");
h.Close;
END Test;
PROCEDURE Test2*;
VAR h : HTTPConnection;
r : Streams.Reader;
res : LONGINT;
f:Files.File;
fr: Files.Reader;
BEGIN
NEW(h);
f:=Files.Old("test.txt"); Files.OpenReader(fr,f,0);
h.Post("http://127.0.0.1/Trap", "sender=myself&receiver=you", "text/plain", fr, f.Length(), r, res);
KernelLog.String("res= "); KernelLog.Int(res, 0); KernelLog.Ln;
WHILE r.res = 0 DO KernelLog.Char(r.Get()) END;
KernelLog.String("Loop finished");
h.Close;
END Test2;
PROCEDURE TestGoogle*;
VAR h : HTTPConnection;
r : Streams.Reader;
res : LONGINT;
BEGIN
NEW(h);
h.requestHeader.useragent := "Mozilla/5.0";
h.Get("http://www.google.ch", TRUE, r, res);
KernelLog.String("res= "); KernelLog.Int(res, 0); KernelLog.Ln;
WHILE r.res = 0 DO KernelLog.Char(r.Get()) END;
KernelLog.String("Loop finished");
h.Close;
END TestGoogle;
BEGIN
NEW(log, "HTTP Client");
log.SetLogToOut(TRUE);
Modules.InstallTermHandler(CleanUp)
END NewHTTPClient.
SystemTools.Free NewHTTPClient ~
NewHTTPClient.Test ~
NewHTTPClient.TestGoogle ~