fphttpclient: what changed
Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.
| Old | New | Line | |
|---|---|---|---|
| 1 | 1 | ## Overview | |
| 2 | 2 | ||
| 3 | - | ||
| 3 | + | fphttpclient is supplied with FPC as part of the [[fcl-web]] package, and can be used by itself as well. | |
| 4 | 4 | ||
| 5 | 5 | ## HTTPS (TLS/SSL) | |
| 6 | 6 | ||
| 7 | - | ||
| 7 | + | Since April 2014, the trunk/development fphttpclient supports SSL/TLS connections using the OpenSSL library (will ship with version 2.8.0 and above). This requires the OpenSSL .so/.dll/.dylib library/libraries to be installed (e.g. present in your application or system directory on Windows). | |
| 8 | 8 | ||
| 9 | - | ||
| 10 | - | ||
| 9 | + | * If you do not use client side certificates, just specifying the proper port (e.g. 443 for https) is enough to enable TLS/SSL as long as you have [OpenSSL libraries](<https://wiki.openssl.org/index.php/Binaries>) installed (or e.g. in the application directory) | |
| 10 | + | * If you want to use e.g. a client side certificate, do something like this: | |
| 11 | 11 | ||
| 12 | - | ||
| 12 | + | ``` | |
| 13 | 13 | uses ...ssockets, sslsockets.. | |
| 14 | - | ||
| 15 | - | ||
| 16 | - | ||
| 17 | - | ||
| 18 | - | ||
| 19 | - | ||
| 20 | - | ||
| 21 | - | ||
| 22 | - | ||
| 23 | - | ||
| 24 | - | ||
| 25 | - | ||
| 26 | - | ||
| 27 | - | ||
| 28 | - | ||
| 29 | - | ||
| 30 | - | ||
| 31 | - | ||
| 32 | - | ||
| 33 | - | ||
| 14 | + | // Callback for setting up SSL client certificate | |
| 15 | + | procedure TSSLHelper.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; | |
| 16 | + | out AHandler: TSocketHandler); | |
| 17 | + | begin | |
| 18 | + | AHandler := nil; | |
| 19 | + | if UseSSL and (FClientCertificate <> '') then | |
| 20 | + | begin | |
| 21 | + | // Only set up client certificate if needed. | |
| 22 | + | // If not, let normal fphttpclient flow create | |
| 23 | + | // required socket handler | |
| 24 | + | AHandler := TSSLSocketHandler.Create; | |
| 25 | + | // Example: use your own client certificate when communicating with the server: | |
| 26 | + | (AHandler as TSSLSocketHandler).Certificate.FileName := FClientCertificate; | |
| 27 | + | end; | |
| 28 | + | end; | |
| 29 | + | ||
| 30 | + | //... and in your TFPHTTPClient creation: | |
| 31 | + | myclient := TFPHTTPClient.Create(nil); | |
| 32 | + | if FClientCertificate <> '' then | |
| 33 | + | myclient.OnGetSocketHandler := @SSLClientCertSetup; | |
| 34 | 34 | ``` | |
| 35 | 35 | ||
| 36 | 36 | ## Examples | |
| 37 | 37 | ||
| 38 | - | ||
| 38 | + | Examples are included in your FPC directory: packages/fcl-web/examples/ | |
| 39 | 39 | ||
| 40 | - | ||
| 40 | + | Apart from those, please see below: | |
| 41 | 41 | ||
| 42 | 42 | ### Get body of a web page via HTTP protocol | |
| 43 | - | ||
| 44 | - | ||
| 43 | + | ``` | |
| 45 | 44 | {$mode delphi} | |
| 46 | - | ||
| 47 | - | ||
| 48 | - | ||
| 49 | - | ||
| 50 | - | ||
| 51 | - | ||
| 52 | - | ||
| 53 | - | ||
| 54 | - | ||
| 55 | - | ||
| 56 | - | ||
| 57 | - | ||
| 58 | - | ||
| 59 | - | ||
| 45 | + | uses fphttpclient; | |
| 46 | + | ||
| 47 | + | Var | |
| 48 | + | URL, S : String; | |
| 49 | + | begin | |
| 50 | + | URL := ParamStr(1); | |
| 51 | + | with TFPHttpClient.Create(Nil) do | |
| 52 | + | try | |
| 53 | + | S := Get(URL); | |
| 54 | + | finally | |
| 55 | + | Free; | |
| 56 | + | end; | |
| 57 | + | Writeln('Content: ', S); | |
| 58 | + | end. | |
| 60 | 59 | ``` | |
| 61 | 60 | ||
| 62 | - | ||
| 63 | - | ||
| 64 | - | ||
| 65 | - | ||
| 61 | + | If you want to write even fewer lines of code, in FPC 2.7.1 you can use the class method: | |
| 66 | 62 | ``` | |
| 63 | + | S := TFPCustomHTTPClient.SimpleGet('http://a_site/a_page'); | |
| 64 | + | ``` | |
| 67 | 65 | ||
| 68 | 66 | ### Download a file via HTTP protocol | |
| 69 | 67 | ||
| 70 | - | ||
| 71 | - | ||
| 72 | - | ||
| 68 | + | Let's show you the simplest example using HTTP only. This example retrieves just an html page and writes it to the screen. | |
| 73 | 69 | ||
| 74 | - | ||
| 70 | + | It uses one of the class **Get** methods of TfpHttpClient. You don't need to create and free the class. There are several overloads for e.g. TStrings or TStream (file) as well: | |
| 71 | + | ``` | |
| 75 | 72 | program dl_fphttp_a; | |
| 76 | - | ||
| 77 | - | ||
| 78 | - | ||
| 79 | - | ||
| 80 | - | ||
| 81 | - | ||
| 73 | + | {$mode delphi}{$ifdef windows}{$apptype console}{$endif} | |
| 74 | + | uses | |
| 75 | + | fphttpclient; | |
| 76 | + | begin | |
| 77 | + | writeln(TFPHttpClient.SimpleGet('http://example.com')); | |
| 78 | + | end. | |
| 82 | 79 | ``` | |
| 83 | 80 | ||
| 84 | - | ||
| 85 | - | ||
| 86 | - | ||
| 81 | + | That's all! For simple purposes this will suffice. You can even use it for HTTPS, which needs just the inclusion of one additional unit: | |
| 82 | + | ``` | |
| 87 | 83 | program dl_fphttp_b; | |
| 88 | - | ||
| 89 | - | ||
| 90 | - | ||
| 91 | - | ||
| 92 | - | ||
| 93 | - | ||
| 94 | - | ||
| 95 | - | ||
| 96 | - | ||
| 97 | - | ||
| 84 | + | ||
| 85 | + | {$mode delphi}{$ifdef windows}{$apptype console}{$endif} | |
| 86 | + | ||
| 87 | + | uses | |
| 88 | + | fphttpclient, | |
| 89 | + | opensslsockets; | |
| 90 | + | ||
| 91 | + | begin | |
| 92 | + | writeln(TFPHttpClient.SimpleGet('https://freepascal.org')); | |
| 93 | + | end. | |
| 98 | 94 | ``` | |
| 99 | 95 | ||
| 100 | - | ||
| 101 | - | ||
| 102 | - | ||
| 96 | + | This really is all there is to do in simple scenarios, usually if you have enough control. | |
| 103 | 97 | ||
| 104 | - | ||
| 98 | + | But there are some caveats with this code. The foremost one being that this code does not allow for redirects. Let me demo that: | |
| 99 | + | ``` | |
| 105 | 100 | program dl_fphttp_redirect_error; | |
| 106 | - | ||
| 107 | - | ||
| 108 | - | ||
| 109 | - | ||
| 110 | - | ||
| 111 | - | ||
| 112 | - | ||
| 113 | - | ||
| 114 | - | ||
| 115 | - | ||
| 101 | + | {$mode delphi}{$ifdef windows}{$apptype console}{$endif} | |
| 102 | + | uses | |
| 103 | + | sysutils, fphttpclient, opensslsockets; | |
| 104 | + | begin | |
| 105 | + | try | |
| 106 | + | writeln(TFPHttpClient.SimpleGet('https://google.com')); | |
| 107 | + | except on E:EHttpClient do | |
| 108 | + | writeln(e.message) else raise; | |
| 109 | + | end; | |
| 110 | + | end. | |
| 116 | 111 | ``` | |
| 117 | 112 | ||
| 118 | - | ||
| 119 | - | ||
| 120 | - | ||
| 113 | + | Because the Google URL uses redirects, there is an exception: **"Unexpected response status code: 301"**. In such a case we need more control, which I will show you in the next example: | |
| 114 | + | ``` | |
| 121 | 115 | program dl_fphttp_c; | |
| 122 | - | ||
| 123 | - | ||
| 124 | - | ||
| 125 | - | ||
| 126 | - | ||
| 127 | - | ||
| 128 | - | ||
| 129 | - | ||
| 130 | - | ||
| 131 | - | ||
| 132 | - | ||
| 133 | - | ||
| 134 | - | ||
| 135 | - | ||
| 136 | - | ||
| 137 | - | ||
| 138 | - | ||
| 139 | - | ||
| 140 | - | ||
| 141 | - | ||
| 142 | - | ||
| 143 | - | ||
| 144 | - | ||
| 145 | - | ||
| 146 | - | ||
| 147 | - | ||
| 116 | + | ||
| 117 | + | {$mode delphi}{$ifdef windows}{$apptype console}{$endif} | |
| 118 | + | ||
| 119 | + | uses | |
| 120 | + | classes, | |
| 121 | + | fphttpclient, | |
| 122 | + | openssl, { This implements the procedure InitSSLInterface } | |
| 123 | + | opensslsockets; | |
| 124 | + | ||
| 125 | + | var | |
| 126 | + | Client: TFPHttpClient; | |
| 127 | + | ||
| 128 | + | begin | |
| 129 | + | ||
| 130 | + | { SSL initialization has to be done by hand here } | |
| 131 | + | InitSSLInterface; | |
| 132 | + | ||
| 133 | + | Client := TFPHttpClient.Create(nil); | |
| 134 | + | try | |
| 135 | + | Client.AddHeader('User-Agent', 'Mozilla/5.0 (compatible; fpweb)'); | |
| 136 | + | { Allow redirections } | |
| 137 | + | Client.AllowRedirect := true; | |
| 138 | + | Client.ConnectTimeout:= 10000; // msec | |
| 139 | + | Client.IOTimeout := 15000; // msec | |
| 140 | + | writeln(Client.Get('https://google.com/')); | |
| 141 | + | finally | |
| 142 | + | Client.Free; | |
| 143 | + | end; | |
| 144 | + | end. | |
| 148 | 145 | ``` | |
| 149 | 146 | ||
| 150 | - | ||
| 151 | - | ||
| 152 | - | ||
| 147 | + | You see this requires slightly more code, but it is still a very small program. Well, now we go to the last example, which downloads any file and saves it to disk. You can use it as a template for your own code, it demonstrates almost everything you need. | |
| 148 | + | ``` | |
| 153 | 149 | program dl_fphttp_d; | |
| 154 | - | ||
| 155 | - | ||
| 156 | - | ||
| 157 | - | ||
| 158 | - | ||
| 159 | - | ||
| 160 | - | ||
| 161 | - | ||
| 162 | - | ||
| 163 | - | ||
| 164 | - | ||
| 165 | - | ||
| 166 | - | ||
| 167 | - | ||
| 168 | - | ||
| 169 | - | ||
| 170 | - | ||
| 171 | - | ||
| 172 | - | ||
| 173 | - | ||
| 174 | - | ||
| 175 | - | ||
| 176 | - | ||
| 177 | - | ||
| 178 | - | ||
| 179 | - | ||
| 180 | - | ||
| 181 | - | ||
| 182 | - | ||
| 183 | - | ||
| 184 | - | ||
| 185 | - | ||
| 186 | - | ||
| 187 | - | ||
| 188 | - | ||
| 189 | - | ||
| 190 | - | ||
| 191 | - | ||
| 192 | - | ||
| 193 | - | ||
| 194 | - | ||
| 195 | - | ||
| 196 | - | ||
| 197 | - | ||
| 198 | - | ||
| 199 | - | ||
| 200 | - | ||
| 201 | - | ||
| 202 | - | ||
| 203 | - | ||
| 204 | - | ||
| 150 | + | ||
| 151 | + | {$mode delphi}{$ifdef windows}{$apptype console}{$endif} | |
| 152 | + | ||
| 153 | + | uses | |
| 154 | + | sysutils, | |
| 155 | + | classes, | |
| 156 | + | fphttpclient, | |
| 157 | + | openssl, | |
| 158 | + | opensslsockets; | |
| 159 | + | ||
| 160 | + | const | |
| 161 | + | Filename = 'testdownload.txt'; | |
| 162 | + | ||
| 163 | + | var | |
| 164 | + | Client: TFPHttpClient; | |
| 165 | + | FS: TStream; | |
| 166 | + | SL: TStringList; | |
| 167 | + | ||
| 168 | + | begin | |
| 169 | + | ||
| 170 | + | { SSL initialization has to be done by hand here } | |
| 171 | + | InitSSLInterface; | |
| 172 | + | ||
| 173 | + | Client := TFPHttpClient.Create(nil); | |
| 174 | + | FS := TFileStream.Create(Filename,fmCreate or fmOpenWrite); | |
| 175 | + | try | |
| 176 | + | try | |
| 177 | + | Client.AddHeader('User-Agent', 'Mozilla/5.0 (compatible; fpweb)'); | |
| 178 | + | { Allow redirections } | |
| 179 | + | Client.AllowRedirect := true; | |
| 180 | + | Client.ConnectTimeout:= 10000; // msec | |
| 181 | + | Client.IOTimeout := 15000; // msec | |
| 182 | + | Client.Get('https://google.com/',FS); | |
| 183 | + | except | |
| 184 | + | on E: EHttpClient do | |
| 185 | + | writeln(E.Message) | |
| 186 | + | else | |
| 187 | + | raise; | |
| 188 | + | end; | |
| 189 | + | finally | |
| 190 | + | FS.Free; | |
| 191 | + | Client.Free; | |
| 192 | + | end; | |
| 193 | + | ||
| 194 | + | { Test our file } | |
| 195 | + | if FileExists(Filename) then | |
| 196 | + | try | |
| 197 | + | SL := TStringList.Create; | |
| 198 | + | SL.LoadFromFile(Filename); | |
| 199 | + | writeln(SL.Text); | |
| 200 | + | finally | |
| 201 | + | SL.Free; | |
| 202 | + | end; | |
| 203 | + | end. | |
| 205 | 204 | ``` | |
| 206 | 205 | ||
| 207 | 206 | ### Get file size from URL | |
| 208 | 207 | ||
| 209 | - | ||
| 210 | - | ||
| 211 | - | ||
| 208 | + | If you will use HTTPS links, you will need to use unit "opensslsockets". The following function assumes that server supports HEAD requests, only rare servers these days do not support it. | |
| 209 | + | ``` | |
| 212 | 210 | uses | |
| 213 | - | ||
| 214 | - | ||
| 215 | - | ||
| 216 | - | ||
| 217 | - | ||
| 218 | - | ||
| 219 | - | ||
| 220 | - | ||
| 221 | - | ||
| 222 | - | ||
| 223 | - | ||
| 224 | - | ||
| 225 | - | ||
| 226 | - | ||
| 227 | - | ||
| 228 | - | ||
| 229 | - | ||
| 211 | + | opensslsockets, fphttpclient; | |
| 212 | + | ||
| 213 | + | function GetRemoteFileSize(const URL: string): Int64; | |
| 214 | + | var | |
| 215 | + | SL: TStringList; | |
| 216 | + | S: string; | |
| 217 | + | begin | |
| 218 | + | SL:= TStringList.Create; | |
| 219 | + | try | |
| 220 | + | TFPHTTPClient.Head(URL, SL); | |
| 221 | + | //SL.NameValueSeparator := ':'; // Already done in TFPCustomHTTPClient.Create() | |
| 222 | + | S:= SL.Values['Content-Length']; | |
| 223 | + | Result:= StrToInt64Def(S, -1); | |
| 224 | + | finally | |
| 225 | + | FreeAndNil(SL); | |
| 226 | + | end; | |
| 227 | + | end; | |
| 230 | 228 | ``` | |
| 231 | 229 | ||
| 232 | 230 | ### Upload a file using POST | |
| 233 | 231 | ||
| 234 | - | ||
| 235 | - | ||
| 236 | - | ||
| 232 | + | Use TFPHTTPClient.FileFormPost(), which allows the caller to specify the path to a local file to be uploaded and the content of the _name_ field (see <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#directives> for more information): | |
| 233 | + | ``` | |
| 237 | 234 | {$mode delphi} | |
| 238 | - | ||
| 239 | - | ||
| 240 | - | ||
| 241 | - | ||
| 242 | - | ||
| 243 | - | ||
| 244 | - | ||
| 245 | - | ||
| 246 | - | ||
| 247 | - | ||
| 248 | - | ||
| 249 | - | ||
| 250 | - | ||
| 251 | - | ||
| 252 | - | ||
| 253 | - | ||
| 254 | - | ||
| 255 | - | ||
| 256 | - | ||
| 257 | - | ||
| 258 | - | ||
| 259 | - | ||
| 260 | - | ||
| 261 | - | ||
| 262 | - | ||
| 263 | - | ||
| 264 | - | ||
| 235 | + | ||
| 236 | + | uses fphttpclient, classes; | |
| 237 | + | ||
| 238 | + | const | |
| 239 | + | FieldName = 'myfield'; { This is the name of the HTTP field in the form you are filling } | |
| 240 | + | FileName = 'test.txt'; { This file must exist on your computer } | |
| 241 | + | ||
| 242 | + | Var | |
| 243 | + | Respo: TStringStream; | |
| 244 | + | S : String; | |
| 245 | + | ||
| 246 | + | begin | |
| 247 | + | With TFPHttpClient.Create(Nil) do | |
| 248 | + | try | |
| 249 | + | Respo := TStringStream.Create(''); | |
| 250 | + | FileFormPost('http://example.com', | |
| 251 | + | FieldName, | |
| 252 | + | FileName, | |
| 253 | + | Respo); | |
| 254 | + | S := Respo.DataString; | |
| 255 | + | WriteLn('Response: '); | |
| 256 | + | WriteLn(S); | |
| 257 | + | Respo.Destroy; | |
| 258 | + | finally | |
| 259 | + | Free; | |
| 260 | + | end; | |
| 261 | + | end. | |
| 265 | 262 | ``` | |
| 266 | 263 | ||
| 267 | - | ||
| 264 | + | There is a method StreamFormPost which will upload a stream instead of directly reading a file. | |
| 268 | 265 | ||
| 269 | 266 | ### Form data and encoding | |
| 270 | - | ||
| 271 | - | ||
| 272 | - | ||
| 273 | 267 | ``` | |
| 274 | - | ||
| 275 | - | ||
| 276 | - | ||
| 268 | + | FormPost(const URL: string; FormData: TStrings; const Response: TStream); | |
| 277 | 269 | ``` | |
| 270 | + | ``` | |
| 271 | + | FormPost(const URL, FormData: string; const Response: TStream); | |
| 272 | + | ``` | |
| 278 | 273 | ||
| 279 | - | ||
| 274 | + | If you pass FormData as [[TStrings]] the FormPost procedure performs _EncodeURLElement_ but if you pass FormData as simple [[string]] to FormPost, then _EncodeURLElement_ is not performed. | |
| 280 | 275 | ||
| 281 | - | ||
| 276 | + | There is no difference in the behaviour if the data in FormData does not need to be encoded, but there is different behaviour for strings which include characters which are not allowed (eg '@', '=', etc). | |
| 282 | 277 | ||
| 283 | 278 | ### Posting JSON | |
| 284 | 279 | ||
| 285 | - | ||
| 286 | - | ||
| 287 | - | ||
| 280 | + | JSON is a popular way for machine to machine talk, and requires that appropriate headers be set. This example sends a short JSON string and gets back, in 'Response' there is some more JSON. | |
| 281 | + | ``` | |
| 288 | 282 | var | |
| 289 | - | ||
| 290 | - | ||
| 291 | - | ||
| 292 | - | ||
| 293 | - | ||
| 294 | - | ||
| 295 | - | ||
| 296 | - | ||
| 297 | - | ||
| 298 | - | ||
| 299 | - | ||
| 300 | - | ||
| 301 | - | ||
| 302 | - | ||
| 303 | - | ||
| 304 | - | ||
| 305 | - | ||
| 306 | - | ||
| 307 | - | ||
| 308 | - | ||
| 309 | - | ||
| 310 | - | ||
| 311 | - | ||
| 312 | - | ||
| 313 | - | ||
| 283 | + | Client: TFPHttpClient; | |
| 284 | + | Response: TStringStream; | |
| 285 | + | Params: string = '{"title": "Some note", "content": "Awesome stuff"}'; | |
| 286 | + | begin | |
| 287 | + | Client := TFPHttpClient.Create(nil); | |
| 288 | + | Client.AddHeader('User-Agent', 'Mozilla/5.0 (compatible; fpweb)'); | |
| 289 | + | Client.AddHeader('Content-Type', 'application/json; charset=UTF-8'); | |
| 290 | + | Client.AddHeader('Accept', 'application/json'); | |
| 291 | + | Client.AllowRedirect := true; | |
| 292 | + | Client.ConnectTimeout := 10000; // msec | |
| 293 | + | Client.IOTimeout := 15000; // msec | |
| 294 | + | Client.UserName := USER_STRING; | |
| 295 | + | Client.Password := PASSW_STRING; | |
| 296 | + | Client.RequestBody := TRawByteStringStream.Create(Params); | |
| 297 | + | Response := TStringStream.Create(''); | |
| 298 | + | try | |
| 299 | + | try | |
| 300 | + | Client.Post(TheURL, Response); | |
| 301 | + | Writeln('Response Code: ' + IntToStr(Client.ResponseStatusCode)); // better be 200 | |
| 302 | + | except on E: Exception do | |
| 303 | + | Writeln('Something bad happened: ' + E.Message); | |
| 304 | + | end; | |
| 305 | + | finally | |
| 306 | + | Client.RequestBody.Free; | |
| 307 | + | Client.Free; | |
| 308 | + | Response.Free; | |
| 309 | + | end; | |
| 314 | 310 | ``` | |
| 315 | 311 | ||
| 316 | - | ||
| 312 | + | Note that using Client.FormPost() will overwrite the content-type header with "application/x-www-form-urlencoded" causing a lot of confusion with a server that is expecting JSON. | |
| 317 | 313 | ||
| 318 | 314 | ### Get external IP address | |
| 319 | 315 | ||
| 320 | - | ||
| 321 | - | ||
| 322 | - | ||
| 316 | + | If your computer is connected to the internet via a LAN (cabled or wireless), the IP address of your network card most probably is not your external IP address. | |
| 323 | 317 | ||
| 324 | - | ||
| 318 | + | You can retrieve your external IP address from e.g. your router or an external site. The code below tries to get it from an external site (thanks to JoStudio on the forum for the inspiration: [[1]](<http://lazarus.freepascal.org/index.php/topic,17506.msg110917.html#msg110917>)): | |
| 319 | + | ``` | |
| 325 | 320 | {$mode objfpc}{$H+} | |
| 326 | - | ||
| 327 | - | ||
| 328 | - | ||
| 329 | - | ||
| 330 | - | ||
| 331 | - | ||
| 332 | - | ||
| 333 | - | ||
| 334 | - | ||
| 335 | - | ||
| 336 | - | ||
| 337 | - | ||
| 338 | - | ||
| 339 | - | ||
| 340 | - | ||
| 341 | - | ||
| 342 | - | ||
| 343 | - | ||
| 344 | - | ||
| 345 | - | ||
| 346 | - | ||
| 347 | - | ||
| 348 | - | ||
| 349 | - | ||
| 350 | - | ||
| 351 | - | ||
| 352 | - | ||
| 353 | - | ||
| 354 | - | ||
| 355 | - | ||
| 356 | - | ||
| 321 | + | ||
| 322 | + | uses | |
| 323 | + | Classes, SysUtils, fphttpclient, RegExpr; | |
| 324 | + | ||
| 325 | + | function GetExternalIPAddress: string; | |
| 326 | + | var | |
| 327 | + | HTTPClient: TFPHTTPClient; | |
| 328 | + | IPRegex: TRegExpr; | |
| 329 | + | RawData: string; | |
| 330 | + | begin | |
| 331 | + | try | |
| 332 | + | HTTPClient := TFPHTTPClient.Create(nil); | |
| 333 | + | IPRegex := TRegExpr.Create; | |
| 334 | + | try | |
| 335 | + | //returns something like: | |
| 336 | + | { | |
| 337 | + | <html><head><title>Current IP Check</title></head><body>Current IP Address: 44.151.191.44</body></html> | |
| 338 | + | } | |
| 339 | + | RawData := HTTPClient.Get('http://checkip.dyndns.org'); | |
| 340 | + | // adjust for expected output; we just capture the first IP address now: | |
| 341 | + | IPRegex.Expression := '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'; | |
| 342 | + | //or '\b(?:\d{1,3}\.){3}\d{1,3}\b' | |
| 343 | + | if IPRegex.Exec(RawData) then | |
| 344 | + | Result := IPRegex.Match[0] | |
| 345 | + | else | |
| 346 | + | Result := 'Got invalid results getting external IP address. Details:' | |
| 347 | + | + LineEnding + RawData; | |
| 348 | + | except | |
| 349 | + | on E: Exception do | |
| 350 | + | begin | |
| 351 | + | Result := 'Error retrieving external IP address: ' + E.Message; | |
| 352 | + | end; | |
| 353 | + | end; | |
| 354 | + | finally | |
| 355 | + | HTTPClient.Free; | |
| 356 | + | IPRegex.Free; | |
| 357 | 357 | end; | |
| 358 | 358 | end; | |
| 359 | - | ||
| 360 | - | ||
| 361 | - | ||
| 362 | - | ||
| 363 | - | ||
| 364 | - | ||
| 365 | - | ||
| 366 | - | ||
| 367 | - | ||
| 359 | + | ||
| 360 | + | begin | |
| 361 | + | Writeln('External IP address:', GetExternalIPAddress); | |
| 362 | + | end. | |
| 368 | 363 | ``` | |
| 369 | 364 | ||
| 370 | 365 | ### Translate text using Google Translate | |
| 371 | 366 | ||
| 372 | 367 | See [[Using Google Translate]] | |
| 373 | 368 | ||
| 374 | 369 | ## See also | |
| 375 | 370 | ||
| 376 | - | ||
| 377 | - | ||
| 378 | - | ||
| 379 | - | ||
| 371 | + | * [[macOS NSURLConnection]] | |
| 372 | + | * [[macOS NSURLSession]] | |
| 373 | + | * [[macOS Programming Tips|macOS OpenSSL, LibreSSL, Secure Transport, Network Framework]] | |
| 374 | + | * [[Windows Programming Tips|Windows native WinInet API]] | |
| 380 | 375 | ||
| 381 | 376 | ## External links | |
| 382 | 377 | ||
| 383 | - | ||
| 378 | + | * [fpHTTPClient Tutorial](<http://lazplanet.blogspot.com/2019/03/how-to-get-contents-of-url-in-2-ways.html>). | |
| 384 | 379 | ||
| 385 | 380 | --- | |
| 386 | - | ||
| 387 | - | ||
| 388 | - | ||
| 389 | - | ||
| 381 | + | *From the Free Pascal wiki, page "fphttpclient", as the Internet Archive kept it on 2026-08-15, last changed on 2026-05-22. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
