WebHTTPClient.Mod 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE WebHTTPClient; (** AUTHOR "TF"; PURPOSE "HTTP client"; *)
  3. IMPORT
  4. TFLog, Streams, Strings, IP, DNS, TCP, TLS, WebHTTP, Modules;
  5. VAR log : TFLog.Log;
  6. CONST Ok* = 0;
  7. TYPE
  8. ContentReader * = OBJECT (Streams.Reader)
  9. VAR
  10. in: Streams.Reader;
  11. encoding: ARRAY 64 OF CHAR;
  12. length: LONGINT;
  13. PROCEDURE & InitContentReader * (in: Streams.Reader; CONST h: WebHTTP.ResponseHeader);
  14. VAR
  15. token: ARRAY 64 OF CHAR;
  16. res: LONGINT;
  17. BEGIN
  18. InitReader(Receive, 1024);
  19. SELF.in := in;
  20. COPY(h.transferencoding, encoding);
  21. IF (encoding # "") & Strings.Match("chunked", encoding) THEN
  22. in.SkipSpaces(); in.Token(token); Strings.HexStrToInt(token, length, res); in.SkipLn();
  23. ELSE
  24. length := h.contentlength;
  25. END;
  26. END InitContentReader;
  27. PROCEDURE Receive * (VAR buf: ARRAY OF CHAR; ofs, size, min: LONGINT; VAR len, res: LONGINT);
  28. VAR
  29. token: ARRAY 16 OF CHAR;
  30. i, total, r: LONGINT;
  31. ch: CHAR;
  32. BEGIN
  33. IF (encoding # "") & Strings.Match("chunked", encoding) THEN
  34. WHILE (length # 0) & (in.res = Streams.Ok) DO
  35. WHILE (total < size) & (i < length) DO
  36. in.Char(ch);
  37. buf[ofs + total] := ch;
  38. INC(i);
  39. INC(total)
  40. END;
  41. i := 0;
  42. in.SkipLn;in.SkipSpaces; in.Token(token); Strings.HexStrToInt(token, length, r); in.SkipLn;
  43. END;
  44. len := total
  45. ELSE
  46. IF length >= 0 THEN
  47. WHILE (i < size) & (i < length) DO in.Char(ch); buf[ofs + i] := ch; INC(i) END;
  48. DEC(length, i);
  49. ELSE
  50. WHILE (in.res = Streams.Ok) & (i < size) DO in.Char(ch); buf[ofs + i] := ch; INC(i) END;
  51. END;
  52. len := i
  53. END;
  54. IF len < min THEN
  55. res := Streams.EOF
  56. ELSE
  57. res := Streams.Ok
  58. END
  59. END Receive;
  60. END ContentReader;
  61. PROCEDURE Head*(CONST url : ARRAY OF CHAR; VAR con : TCP.Connection; VAR header: WebHTTP.ResponseHeader; VAR res : LONGINT);
  62. VAR
  63. host : ARRAY 128 OF CHAR;
  64. path : ARRAY 256 OF CHAR;
  65. port : LONGINT;
  66. fadr : IP.Adr;
  67. w : Streams.Writer;
  68. r : Streams.Reader;
  69. BEGIN
  70. IF WebHTTP.SplitHTTPAdr(url, host, path, port) THEN
  71. IF path = "" THEN path := "/" END;
  72. DNS.HostByName(host, fadr, res);
  73. IF res = DNS.Ok THEN
  74. IF con = NIL THEN NEW(con); con.Open(TCP.NilPort, fadr, port, res); END;
  75. IF res = TCP.Ok THEN
  76. Streams.OpenWriter(w, con.Send);
  77. Streams.OpenReader(r, con.Receive);
  78. WebHTTP.WriteRequestLine(w, 1, 1, WebHTTP.HeadM, path, host); w.Ln(); w.Update();
  79. WebHTTP.ParseReply(r, header, res, log);
  80. IF res = WebHTTP.OK THEN res := Ok END;
  81. con.Close
  82. ELSE
  83. log.Enter; log.String("Head could not connect to : "); log.String(host); log.Exit
  84. END
  85. ELSE
  86. log.Enter; log.String("Host not found : "); log.String(host); log.Exit
  87. END;
  88. END;
  89. END Head;
  90. (** The HTTP versions is ignored and set to 1.0; uri and host are ignored and taken from the url parameter *)
  91. PROCEDURE Get*(CONST url : ARRAY OF CHAR; VAR rHeader : WebHTTP.RequestHeader;
  92. VAR con : TCP.Connection; VAR header: WebHTTP.ResponseHeader; VAR out : Streams.Reader; VAR res : LONGINT);
  93. VAR
  94. host : ARRAY 128 OF CHAR;
  95. path : ARRAY 256 OF CHAR;
  96. port : LONGINT;
  97. fadr : IP.Adr;
  98. w : Streams.Writer;
  99. x : WebHTTP.AdditionalField;
  100. tls: TLS.Connection;
  101. BEGIN
  102. IF WebHTTP.SplitHTTPAdr(url, host, path, port) THEN
  103. IF path = "" THEN path := "/" END;
  104. DNS.HostByName(host, fadr, res);
  105. IF res = DNS.Ok THEN
  106. IF con = NIL THEN
  107. IF port = WebHTTP.HTTPPort THEN
  108. NEW(con);
  109. ELSE
  110. NEW(tls);
  111. con := tls;
  112. END;
  113. con.Open(TCP.NilPort, fadr, port, res);
  114. END;
  115. IF res = TCP.Ok THEN
  116. Streams.OpenWriter(w, con.Send);
  117. Streams.OpenReader(out, con.Receive);
  118. WebHTTP.WriteRequestLine(w, 1, 0, WebHTTP.GetM, path, host);
  119. IF rHeader.referer # "" THEN w.String("Referer: "); w.String(rHeader.referer); w.Ln() END;
  120. IF rHeader.useragent # "" THEN w.String("User-Agent: "); w.String(rHeader.useragent); w.Ln() END;
  121. IF rHeader.accept # "" THEN w.String("Accept: "); w.String(rHeader.accept); w.Ln() END;
  122. x := rHeader.additionalFields;
  123. WHILE x # NIL DO
  124. w.String(x.key); w.Char(" "); w.String(x.value);w.Ln();
  125. x := x.next
  126. END;
  127. w.Ln(); w.Update();
  128. WebHTTP.ParseReply(out, header, res, log);
  129. WebHTTP.LogResponseHeader(log, header);
  130. IF res = WebHTTP.OK THEN res := Ok END;
  131. ELSE
  132. log.Enter; log.String("Get could not connect to : "); log.String(host); log.Exit
  133. END
  134. ELSE
  135. log.Enter; log.String("Host not found : "); log.String(host); log.Exit
  136. END;
  137. END
  138. END Get;
  139. PROCEDURE CleanUp;
  140. BEGIN
  141. log.Close
  142. END CleanUp;
  143. BEGIN
  144. NEW(log, "HTTP Client");
  145. log.SetLogToOut(FALSE);
  146. Modules.InstallTermHandler(CleanUp)
  147. END WebHTTPClient.