123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
- MODULE WebHTTPClient; (** AUTHOR "TF"; PURPOSE "HTTP client"; *)
- IMPORT
- TFLog, Streams, Strings, IP, DNS, TCP, TLS, WebHTTP, Modules;
- VAR log : TFLog.Log;
- CONST Ok* = 0;
- TYPE
- ContentReader * = OBJECT (Streams.Reader)
- VAR
- in: Streams.Reader;
- encoding: ARRAY 64 OF CHAR;
- length: LONGINT;
- PROCEDURE & InitContentReader * (in: Streams.Reader; CONST h: WebHTTP.ResponseHeader);
- VAR
- token: ARRAY 64 OF CHAR;
- res: LONGINT;
- BEGIN
- InitReader(Receive, 1024);
- SELF.in := in;
- COPY(h.transferencoding, encoding);
- IF (encoding # "") & Strings.Match("chunked", encoding) THEN
- in.SkipSpaces(); in.Token(token); Strings.HexStrToInt(token, length, res); in.SkipLn();
- ELSE
- length := h.contentlength;
- END;
- END InitContentReader;
- PROCEDURE Receive * (VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
- VAR
- token: ARRAY 16 OF CHAR;
- i, total, r: LONGINT;
- ch: CHAR;
- BEGIN
- IF (encoding # "") & Strings.Match("chunked", encoding) THEN
- WHILE (length # 0) & (in.res = Streams.Ok) DO
- WHILE (total < size) & (i < length) DO
- in.Char(ch);
- buf[ofs + total] := ch;
- INC(i);
- INC(total)
- END;
- i := 0;
- in.SkipLn;in.SkipSpaces; in.Token(token); Strings.HexStrToInt(token, length, r); in.SkipLn;
- END;
- len := total
- ELSE
- IF length >= 0 THEN
- WHILE (i < size) & (i < length) DO in.Char(ch); buf[ofs + i] := ch; INC(i) END;
- DEC(length, i);
- ELSE
- WHILE (in.res = Streams.Ok) & (i < size) DO in.Char(ch); buf[ofs + i] := ch; INC(i) END;
- END;
- len := i
- END;
- IF len < min THEN
- res := Streams.EOF
- ELSE
- res := Streams.Ok
- END
- END Receive;
- END ContentReader;
- PROCEDURE Head*(CONST url : ARRAY OF CHAR; VAR con : TCP.Connection; VAR header: WebHTTP.ResponseHeader; VAR res : LONGINT);
- VAR
- host : ARRAY 128 OF CHAR;
- path : ARRAY 256 OF CHAR;
- port : LONGINT;
- fadr : IP.Adr;
- w : Streams.Writer;
- r : Streams.Reader;
- BEGIN
- IF WebHTTP.SplitHTTPAdr(url, host, path, port) THEN
- IF path = "" THEN path := "/" END;
- DNS.HostByName(host, fadr, res);
- IF res = DNS.Ok THEN
- IF con = NIL THEN NEW(con); con.Open(TCP.NilPort, fadr, port, res); END;
- IF res = TCP.Ok THEN
- Streams.OpenWriter(w, con.Send);
- Streams.OpenReader(r, con.Receive);
- WebHTTP.WriteRequestLine(w, 1, 1, WebHTTP.HeadM, path, host); w.Ln(); w.Update();
- WebHTTP.ParseReply(r, header, res, log);
- IF res = WebHTTP.OK THEN res := Ok END;
- con.Close
- ELSE
- log.Enter; log.String("Head could not connect to : "); log.String(host); log.Exit
- END
- ELSE
- log.Enter; log.String("Host not found : "); log.String(host); log.Exit
- END;
- END;
- END Head;
- (** The HTTP versions is ignored and set to 1.0; uri and host are ignored and taken from the url parameter *)
- PROCEDURE Get*(CONST url : ARRAY OF CHAR; VAR rHeader : WebHTTP.RequestHeader;
- VAR con : TCP.Connection; VAR header: WebHTTP.ResponseHeader; VAR out : Streams.Reader; VAR res : LONGINT);
- VAR
- host : ARRAY 128 OF CHAR;
- path : ARRAY 256 OF CHAR;
- port : LONGINT;
- fadr : IP.Adr;
- w : Streams.Writer;
- x : WebHTTP.AdditionalField;
- tls: TLS.Connection;
- BEGIN
- IF WebHTTP.SplitHTTPAdr(url, host, path, port) THEN
- IF path = "" THEN path := "/" END;
- DNS.HostByName(host, fadr, res);
- IF res = DNS.Ok THEN
- IF con = NIL THEN
- IF port = WebHTTP.HTTPPort THEN
- NEW(con);
- ELSE
- NEW(tls);
- con := tls;
- END;
- con.Open(TCP.NilPort, fadr, port, res);
- END;
- IF res = TCP.Ok THEN
- Streams.OpenWriter(w, con.Send);
- Streams.OpenReader(out, con.Receive);
- WebHTTP.WriteRequestLine(w, 1, 0, WebHTTP.GetM, path, host);
- IF rHeader.referer # "" THEN w.String("Referer: "); w.String(rHeader.referer); w.Ln() END;
- IF rHeader.useragent # "" THEN w.String("User-Agent: "); w.String(rHeader.useragent); w.Ln() END;
- IF rHeader.accept # "" THEN w.String("Accept: "); w.String(rHeader.accept); w.Ln() END;
- x := rHeader.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(out, header, res, log);
- WebHTTP.LogResponseHeader(log, header);
- IF res = WebHTTP.OK THEN res := Ok END;
- ELSE
- log.Enter; log.String("Get could not connect to : "); log.String(host); log.Exit
- END
- ELSE
- log.Enter; log.String("Host not found : "); log.String(host); log.Exit
- END;
- END
- END Get;
- PROCEDURE CleanUp;
- BEGIN
- log.Close
- END CleanUp;
- BEGIN
- NEW(log, "HTTP Client");
- log.SetLogToOut(FALSE);
- Modules.InstallTermHandler(CleanUp)
- END WebHTTPClient.
|