Add automatic handling of http redirects and passwords in fphttpclient.pp
Original Reporter info from Mantis: Michalis @michaliskambi
-
Reporter name: Michalis Kamburelis
Original Reporter info from Mantis: Michalis @michaliskambi
- Reporter name: Michalis Kamburelis
Description:
This is a feature request, but if you agree --- I am very willing to create a patch to actually implement this :)
- Right now, fphttpclient doesn't handle redirects. The simple TFPCustomHTTPClient.Get method only accepts status code 200 (Ok).
It is possible to support redirects in your code by using more flexible TFPCustomHTTPClient.HTTPMethod and accepting status codes 301, 302, 303, 307 (see http://en.wikipedia.org/wiki/HTTP_302). When receiving such status code you can read Location from ResponseHeaders and then make another request (preferably having some MaxRedirects counter to avoid infinite redirects). I implemented such thing in my Castle Game Engine (see CastleDownload.pas unit, http://svn.code.sf.net/p/castle-engine/code/trunk/castle_game_engine/src/net/castledownload.pas ).
I think it would be nice to handle redirects "out of the box" by TFPCustomHTTPClient.Get. My proposition is to add TFPCustomHTTPClient.MaxRedirects property, and modify TFPCustomHTTPClient.Get to use it. It would call DoMethod('GET',AURL,Stream,[200, 301, 302, 303, 307]) and when status is <> 200 it would read Location from headers and make another DoMethod('GET',...) call. MaxRedirects (I use 32 for my code) would limit the number of possible redirects. Setting TFPCustomHTTPClient.MaxRedirects to zero would also enable the user code to disable automatic redirect following.
- Right now, fphttpclient can pass HTTP username/password (for basic HTTP authentication) only when they are encoded in URI (this happens in TFPCustomHTTPClient.SendRequest). It would be good to extend TFPCustomHTTPClient with properties Username, Password and
2,1. TFPCustomHTTPClient.SendRequest should pass TFPCustomHTTPClient.Username, TFPCustomHTTPClient.Password if provided in the properties (and not present in URI).
2.2. Extend TFPCustomHTTPClient.Get to accept additional http status code 401, upon which an event like OnPassword is fired. Like
OnPassword = function (var RepeatRequest: boolean) of object;
called like
RepeatRequest := false;
if Assigned(OnPassword) then
OnPassword(RepeatRequest);
if RepeatRequest then
... then do the request again, assuming that OnPassword event set new TFPCustomHTTPClient.Username/Password values.
The OnPassword event can (and should) set TFPCustomHTTPClient.Username, TFPCustomHTTPClient.Password and return true to indicate that request should be repeated. User code can e.g. present a GUI option asking user to provide username/password, or cancel.
The above proposition tries to include various scenarios:
- User code may have the HTTP username/password for this server already cached (in memory or even in some config file; browsers commonly cache such passwords, and use them for matching server names). In this case it can set TFPCustomHTTPClient.Username and TFPCustomHTTPClient.Password before calling Get, and the request will succeed (immediately, without a round-trip to the server with 401 answer in the middle).
- When the username/password is not cached (or the current values are incorrect), user code will have a means to ask the user for input.
Note that I don't suggest caching usernames/passwords at the FpHttpClient. Such functionality should be handled by the outside code, if necessary, IMHO. I only propose to add 2 properties and 1 event to make proving HTTP username/password easy.
Mantis conversion info:
- Mantis ID: 24335
- Version: 2.6.2
- Fixed in version: 3.0.0
- Fixed in revision: 26679 (#2cbb9daa)
- Target version: 3.0.0