I am trying to create a little tool that will monitor how much bandwidth I have used and how much I have remaining from my ISP. They have a SOAP service which I must authenticate my UserName and Password and validate the client then I will get 2 GUIDS that must be passed into the function that will return the usage statistics from an array. These are then cached for 1 hour and I must authenticate again.
I have used the WSDL Importer from within Delphi 2010 and it has generated me a Unit. (I am not really sure that I should post this as it is quite large)?
I am trying to authenticate the first part with my Username and Password with the code below:
procedure TForm1.btnAuthClick(Sender: TObject);
var
fGUID: string;
begin
HTTPRIO1.URL := 'https://webservices.zen.co.uk/broadband/v3.11/serviceengine.asmx?WSDL';
try
fGUID := (HTTPRIO1 as ServiceEngineSoap).Authenticate(edtUserName.Text,edtPassword.Text);
Label1.Caption := fGUID;
except
on E: Exception do
Memo1.Lines.Text := E.Message;
end;
end;
The above code always returns the Error below:
Header http://schemas.xmlsoap.org/ws/2004/08/addressing:Action for ultimate recipient is required but not present in the message.
I have tried using the WSDLLocation instead with the Service and the Port:
procedure TForm1.btnAuthClick(Sender: TObject);
var
fGUID: string;
begin
HTTPRIO1.WSDLLocation := 'https://webservices.zen.co.uk/broadband/v3.11/serviceengine.asmx?WSDL';
HTTPRIO1.Service := 'ServiceEngine';
HTTPRIO1.Port := 'ServiceEngineSoap';
try
fGUID := (HTTPRIO1 as ServiceEngineSoap).Authenticate(edtUserName.Text,edtPassword.Text);
Label1.Caption := fGUID;
except
on E: Exception do
Memo1.Lines.Text := E.Message;
end;
end;
This will always generate the Error below:
Unable to retrieve the URL endpoint for Service/Port 'ServiceEngine'/'ServiceEngineSoap' from WSDL 'https://webservices.zen.co.uk/broadband/v3.11/serviceengine.asmx?WSDL'
What am I doing wrong here? If I should actually send a Header then how would I do this to authenticate myself to the service?
According to the docs
if the server requires authentication, use the properties of the THTTPReqResp object to provide the necessary information
It's in the THTTPReqResp object that you set the user/pw (HTTPRIO1.HTTPWebNode.UserName := 'xxx'; HTTPRIO1.HTTPWebNode.Password := 'yyy')
Also note from the docs on using HTTPS:
THTTPReqResp uses WinInet to establish a connection to the server. Wininet.dll must be installed on the client system. wininet.dll is found in the Windows system directory if you have IE3 or higher installed. WinInet has the advantage that it provides support for secure connections (https). To use WinInet, compile your project without the USE_INDY symbol defined
However, it looks like this user/pw may only be used in a Proxy situation according to the post below. Follow Jean-Marie Babet's link to the original workaround given from 2007 if they still haven't fixed this:
https://forums.codegear.com/thread.jspa?threadID=58755&tstart=0
Here's the workaround:
All you have to do is handle the OnBeforePost event on the HTTPRIO.HTTPWebNode component and use InternetSetOption. Here's an example from a sample that talks to MapPoint (MapPoint.NET uses 'digest' authentication - a variant of 'basic' authentication):
procedure TTestMapPointRender.HTTPRIO1HTTPWebNode1BeforePost(
const HTTPReqResp: THTTPReqResp; Data: Pointer);
var
UserName: string;
PassWord: string;
begin
UserName := GetWSToken('MapPoint', 'UserName');
Password := GetWSToken('MapPoint', 'Password');
if not InternetSetOption(Data,
INTERNET_OPTION_USERNAME,
PChar(UserName),
Length(UserName)) then
raiseException(SysErrorMessage(GetLastError));
if not InternetSetOption(Data,
INTERNET_OPTION_PASSWORD,
PChar(Password),
Length (Password)) then
raiseException(SysErrorMessage(GetLastError));
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With