nettobac  0.0.0
Network features for FreeBASIC code
nettobac_http.bas
Go to the documentation of this file.
1 /'* \file nettobac_http.bas
2 \brief Utility functions to handle http requests
3 
4 This file contains
5 
6 - constants for end of line, header
7 - enumerators for mime types and a function to create a type string
8 - functions to create http requests (low level API)
9 - a function to download a file (high level API)
10 
11 Copyright (C) LGPLv2.1, see ReadMe.md for details.
12 
13 \since 0.0.0
14 '/
15 
16 CONST AS STRING _
17  LINEEND = !"\r\n" _ '*< The line end characters
18  , HEADEREND = !"\r\n\r\n" '*< The end of header characters
19 
20 ENUM MimeTypes
21  MIME_HTM = &b0000000000000 '*< Mime type "text/html"
22  MIME_TXT = &b0000000000010 '*< Mime type "text/plain"
23  MIME_BMP = &b0000000000100 '*< Mime type "image/bmp"
24  MIME_GIF = &b0000000001000 '*< Mime type "image/gif"
25  MIME_JPG = &b0000000010000 '*< Mime type "image/jpeg"
26  MIME_PNG = &b0000000100000 '*< Mime type "image/png"
27  MIME_TIF = &b0000001000000 '*< Mime type "image/tiff"
28  MIME_WAV = &b0000010000000 '*< Mime type "audio/wav"
29  MIME_MP3 = &b0000100000000 '*< Mime type "audio/mpeg"
30  MIME_OGG = &b0001000000000 '*< Mime type "audio/ogg"
31  MIME_PDF = &b0010000000000 '*< Mime type "application/pdf"
32  MIME_ZIP = &b0100000000000 '*< Mime type "application/x-compressed"
33  MIME_GZ = &b1000000000000 '*< Mime type "application/gzip"
34 END ENUM
35 
36 
37 /'* \brief Create a text version of the mime type bit mask
38 \param Typ the bitmask containing the type bits (see enumerator #MimeTypes)
39 \returns the text list of mime types (`;` separated)
40 
41 Mime types get handled as a bit mask at module level, for better
42 readability. This function translate the bit mask in to a STRING
43 representation.
44 
45 \since 0.0.0
46 '/
47 FUNCTION MimeType(BYVAL Typ AS MimeTypes) AS STRING
48  VAR r = ""
49  IF Typ AND MIME_HTM THEN r &= ";text/html"
50  IF Typ AND MIME_TXT THEN r &= ";text/plain"
51  IF Typ AND MIME_BMP THEN r &= ";image/bmp"
52  IF Typ AND MIME_GIF THEN r &= ";image/gif"
53  IF Typ AND MIME_JPG THEN r &= ";image/jpeg"
54  IF Typ AND MIME_PNG THEN r &= ";image/png"
55  IF Typ AND MIME_TIF THEN r &= ";image/tiff"
56  IF Typ AND MIME_WAV THEN r &= ";audio/wav"
57  IF Typ AND MIME_MP3 THEN r &= ";audio/mpeg"
58  IF Typ AND MIME_OGG THEN r &= ";audio/ogg"
59  IF Typ AND MIME_PDF THEN r &= ";application/pdf"
60  IF Typ AND MIME_ZIP THEN r &= ";application/x-compressed"
61  IF Typ AND MIME_GZ THEN r &= ";application/gzip"
62  RETURN MID(r, 2)
63 END FUNCTION
64 
65 
66 /'* \brief Encode an URL text
67 \param Url the URL text
68 \returns the encoded version of the input
69 
70 Encode special characters in an URL. Normal characters are
71 
72 - A to Z
73 - a to z
74 - 0 to 9
75 - `_` (underscore), `/` (slash)
76 
77 All other characters get replaced by their `%<hexval>` representation.
78 
79 \since 0.0.0
80 '/
81 FUNCTION urlEncode(BYREF Url AS STRING) AS STRING
82  VAR r = ""
83  FOR i AS INTEGER = 0 TO LEN(Url) - 1
84  SELECT CASE AS CONST Url[i]
85  CASE ASC("_"), ASC("/") _
86  , ASC("0") TO ASC("9") _
87  , ASC("A") TO ASC("Z") _
88  , ASC("a") TO ASC("z") : r += CHR(Url[i])
89  CASE ELSE : r += "%" & LCASE(HEX(Url[i], 2))
90  END SELECT
91  NEXT : RETURN TRIM(r)
92 END FUNCTION
93 
94 
95 /'* \brief Decode an URL text
96 \param Url the encoded URL text
97 \returns the decodeded version of the input
98 
99 Decode special characters in an URL. The `%<hexval>` representations
100 get resolved in to the related characters.
101 
102 \since 0.0.0
103 '/
104 FUNCTION urlDecode(BYREF Url AS STRING) AS STRING
105  Url = TRIM(Url)
106  VAR l = LEN(Url), i = 0, r = ""
107  FOR i AS INTEGER = 0 TO l - 1
108  SELECT CASE AS CONST Url[i]
109  CASE ASC("%") : i += 2 : r &= CHR(VAL("&H" & MID(Url, i, 2)))
110  CASE ELSE : r &= CHR(Url[i])
111  END SELECT
112  NEXT : RETURN r
113 END FUNCTION
114 
115 
116 /'* \brief Create a HTTP GET request
117 \param Host the host adress (ie. `"domain.com"`)
118 \param Targ the path to search for (ie. `"img/test.jpg"`)
119 \param Mime the mime type (ie. `MIME_JPG`, see #MimeTypes)
120 \returns the complete http request STRING
121 
122 Requests a representation of the specified resource.
123 
124 \since 0.0.0
125 '/
126 FUNCTION httpGetReq(BYREF Host AS STRING, BYREF Targ AS STRING, BYVAL Mime AS MimeTypes = MIME_HTM OR MIME_TXT) AS STRING
127  VAR r = "GET " & Targ & " HTTP/1.1" & LINEEND _
128  & "Host: " & Host & LINEEND
129  IF LEN(Mime) THEN r &= "Mime: " & MimeType(Mime) & LINEEND
130  RETURN r & "Connection: close" & HEADEREND
131 END FUNCTION
132 
133 
134 /'* \brief Create a HTTP HEAD request
135 \param Host the host adress (ie. `"domain.com"`)
136 \param Targ the path to search for (ie. `"html/index.html"`)
137 \param Mime the mime type (ie. `MIME_HTM`, see #MimeTypes)
138 \returns the request STRING
139 
140 Asks for the response identical to the one that would correspond to a
141 GET request, but without the response body. It's possible to extract
142 the content length and Mime type from it.
143 
144 \since 0.0.0
145 '/
146 FUNCTION httpHeadReq(BYREF Host AS STRING, BYREF Targ AS STRING, BYVAL Mime AS MimeTypes = MIME_HTM OR MIME_TXT) AS STRING
147  VAR r = "HEAD " & Targ & " HTTP/1.1" & LINEEND _
148  & "Host: " & Host & LINEEND
149  IF LEN(Mime) THEN r &= "Mime: " & MimeType(Mime) & LINEEND
150  RETURN r & "Connection: close" & HEADEREND
151 END FUNCTION
152 
153 
154 /'* \brief Create a HTTP POST request
155 \param Host the host adress (ie. `"domain.com"`)
156 \param Targ the path to search for (ie. `"data/script.php"`)
157 \param Query (ie. `"key1=value&key2=value"`)
158 \param Refer if a `Referer:` should get added
159 \returns the request STRING
160 
161 Requests that the server accept the entity enclosed in the request as a
162 new subordinate of the web resource identified by the URI.
163 
164 \since 0.0.0
165 '/
166 FUNCTION httpPostReq(BYREF Host AS STRING, BYREF Targ AS STRING, BYREF Query AS STRING, BYVAL Refer AS INTEGER = 1) AS STRING
167  VAR r = "POST " & Targ & " HTTP/1.1" & LINEEND _
168  & "Host: " & Host & LINEEND
169  IF Refer THEN r &= "Referer: http://" & Host & Targ & "?" & LINEEND
170  RETURN r _
171  & "Content-type: application/x-www-form-urlencoded" & LINEEND _
172  & "Content-length: " & LEN(Query) & LINEEND _
173  & "Connection: close" & HEADEREND _
174  & Query
175 END FUNCTION
176 
177 
178 /'* \brief Create a HTTP HEAD request
179 \param Host the host adress (ie. `"domain.com"`)
180 \param Targ the path to search for (ie. `"data/test.txt"`)
181 \param Content any content (defaults to `""`)
182 \returns the request STRING
183 
184 Requests that the enclosed entity be stored under the supplied URI.
185 
186 \since 0.0.0
187 '/
188 FUNCTION httpPutReq(BYREF Host AS STRING, BYREF Targ AS STRING, BYREF Content AS STRING = "") AS STRING
189  VAR r = "PUT " & Targ & " HTTP/1.1" & LINEEND _
190  & "Host: " & Host & LINEEND
191  RETURN r & Content
192 END FUNCTION
193 
194 
195 /'* \brief Load a file over network via http protocol
196 \param Res a STRING variable to append the result
197 \param Adr the address of the target (ie. `freebasic.net/index.html`)
198 \param Mim the mime type (see enumerators #MimeTypes)
199 \param Port The port number to use (defaults to 80)
200 \param Mo the modus which data the result variable `Res` should contain
201 \returns the requested file context, if OK
202 
203 This function loads a file over a network connection. It tries to
204 
205 - create a nettobacClient instance to the server adress
206 - open a n2bConnetion
207 - request the target file
208 - receive the http reponse
209 - check the http header
210  - if header OK, strip header and return data only
211  - if not OK, return all data unchanged
212 - delete the nettobacClient instance (and close the n2bConnetion)
213 
214 An error check gets done after each step. In case of an error the
215 function breaks and the error text gets returned. Otherwise the return
216 value 0 (zero) indicates successful operation.
217 
218 \note Although the result variable `Res` may contains data, the function
219  can report an error (ie. when the connection gets lost during
220  transfer). It's recommended to check `.Errr` always.
221 
222 \note By default the http header gets checked and if it includes
223  `200 OK` it gets extracted from the result variable `Res` (only
224  data get returned). In order to receive the header (unchecked) as
225  well, set bit 0 in the modus parameter (`Mo OR= &b1`).
226 
227 \note The received data get appended to result variable `Res`. In order
228  to reset the result STRING (`Res = ""`) before operaion, set bit
229  1 in the modus parameter (`Mo OR= &b10`).
230 
231 \since 0.0.0
232 '/
233 FUNCTION httpLoad(BYREF Res AS STRING, BYREF Adr AS STRING, BYVAL Mim AS MimeTypes = MIME_HTM OR MIME_TXT _
234  , BYVAL Port AS USHORT = 80, BYVAL Mo AS SHORT = &b10) AS CONST ZSTRING CONST PTR
235 '&nettobacClient* client; n2bConnection* conn;
236  VAR p = INSTR(Adr, "/") _
237  , server = LEFT(Adr, p - 1) _
238  , client = NEW nettobacClient(server, Port) _ ' connect to web server at port (default 80)
239  , r = client->Errr
240  IF 0 = r THEN
241  VAR conn = client->nOpen() ' get a connection
242  WITH *client : DO
243  IF .Errr THEN r = .Errr : EXIT DO ' no connection
244 
245  VAR req = HttpGetReq(server, MID(Adr, p), Mim) ' build request
246  conn->nPut(SADD(req), LEN(req)) : IF .Errr THEN r = .Errr : EXIT DO ' put failed
247 
248  IF BIT(Mo, 1) THEN Res = "" ' user wants to reset data
249  conn->nGet(Res) : IF .Errr THEN r = .Errr : EXIT DO ' get failed
250 
251  IF BIT(Mo, 0) /' user wants all data, incl. header '/ THEN EXIT DO
252  p = INSTR(Res, HEADEREND) ' search position of HTTP header end
253  IF INSTRREV(Res, "200 OK", p) < 1 THEN r = @"http header check" : EXIT DO
254  Res = MID(Res, p + 4) : LOOP UNTIL 1
255  END WITH
256  END IF : DELETE client : RETURN r
257 END FUNCTION
258