Ma egy olyan webszolgáltatást kellett meghívnom, ami előtt egy tűzfal csak bizonyos IP című kliensekről engedélyezi a hozzáférést. Ez normális esetben nem is szokott gondot okozni, most is megbeszéltem az ottani rendszergazdákkal, hogy milyen IP címről akarom küldeni a kérést, és ők készségesen lyukat ütöttek a tűzfalba. A nehezítést az jelentette, hogy a hívó épp egy szerver, aminek több IP címe van, és persze alapból nem arról ment ki a kérés, ahonnan én akartam. A kérdés tehát, hogy hogyan lehet megadni egy webszolgáltatás hívásnál a hívó IP címét?
A dolog szerencsére megoldható, de nem olyan egyszerűen, mint szeretnénk. A Visual Studio varázslója olyan proxy osztályt generál, ami a SoapHttpClientProtocol ősosztályból származik, aminek persze egy fikarcnyi ide vágó property-je sincsen. Viszont a HTTP híváshoz ő belül a HttpWebRequest osztályt használja, amin szerencsére lehet ilyen jellegű fogódzót találni. Persze csak alapos kereséssel, ugyanis a tulajdonságot úgy hívják, hogy ServicePoint, aminek a BindIPEndPointDelegate tulajdonságát (!) kell beállítani egy delegate-re! Én bizony ezt biztosan nem így csináltam volna, de gondolom jó okuk volt rá, hogy így döntöttek.
Sajnos a belső WebRequest példány szintén nincs kivezetve a SOAP proxy osztályban, így nincs más lehetőségünk, mint a VS által generált proxy osztályból egy újabb osztályt származtatni, és ott felülírni azt a metódust, ami a WebRequest példány előállításáért felelős. Miután ezt így fejben levezette az ember, a kód már meglehetősen rövid:
class MyServiceWrapper : MyVSGeneratedServiceProxyClass
{
public IPAddress SourceIPAddress { get; set; }
protected override WebRequest GetWebRequest( Uri uri )
{
HttpWebRequest request = (HttpWebRequest) base.GetWebRequest( uri );
request.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(
delegate( ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount )
{
return new IPEndPoint( this.SourceIPAddress, 0 );
});
return request;
}
}
Persze akinek nem jön be ez a tömör névtelen metódusos megoldás, az írhat olvashatóbb kódot két metódusba:
protected override WebRequest GetWebRequest( Uri uri )
{
HttpWebRequest request = (HttpWebRequest) base.GetWebRequest( uri );
request.ServicePoint.BindIPEndPointDelegate =
new BindIPEndPoint( this.OnBindIPEndPoint );
return request;
}
private IPEndPoint OnBindIPEndPoint( ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount )
{
return new IPEndPoint( this.SourceIPAddress, 0 );
}
Végül már csak annyi dolgunk maradt, hogy a Studio által generált osztály helyett a sajátunkat példányosítjuk és beállítjuk a SourceIPAddress tulajdonságot a kívánt IP címre.
Technorati-címkék:
webservice