Aklımda Kalası Kelimeler

* давайте работать вместе
* Zarf ve Mazruf, Zerafet(xHoyratlık) ile aynı kökten(za-ra-fe) gelir
* Bedesten
* Suç subuta ermiştir - Suç sabit olmuştur

16 Nisan 2015 Perşembe

Fiddler ile SQL Server'dan yapılan Web Servis Çağrılarını İzlemek

Fiddler and Microsoft Sql Server

SQL Prosedürmüzde sp_OACreate ile Web Servisi çağrısı yapacağımız bir OLE nesnesi örneğini yaratıp üstünden bir HTTP paketi gönderebiliriz ama Fiddler bunu göstermeyecek. Haydi başlayalım...
Temel itibarıyla aşağıdaki basit kod ile herhangi bir web sayfasını mssql içinden çağırabilirsiniz:
DECLARE @Request INT,
  @hr INT,
  @activeX VARCHAR(50) = 'Msxml2.ServerXMLHTTP.6.0';

 SET @activeX = '{88d96a0b-f192-11d4-a65f-0040963251e5}';
 EXEC @hr = sp_OACreate @activeX, @Request OUT;
 SELECT @hr, @Request
 
 EXEC sp_OAMethod @Request, 'open', NULL, 'GET','https://www.random.org/cgi-bin/randbyte?nbytes=1307&format=h', 'false'
 EXEC sp_OAMethod @Request, 'send', null, ''
  
 DECLARE @ResponseText Varchar(4000)
 EXEC sp_OAMethod @Request, 'responseText', @ResponseText OUTPUT
 SELECT @ResponseText
 Exec sp_OADestroy @Request
 
 IF @hr <> 0
 BEGIN
       DECLARE @src varchar(255), @desc varchar(255)
    EXEC sp_OAGetErrorInfo @Request, @src OUT, @desc OUT 
    SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
    RETURN
 END
 ELSE
    Exec sp_OADestroy @Request

Ekşi Sözlük'te Ole tanımları:
Biraz anlatayım ne nedir diye. sp_OACreate ile MSSQL içinde bir OLE nesnesinin örneğini yaratır.

ole 2.0 kendi icinde (bkz: com) (bkz: activex) gibi teknolojileri icherir..

nesne baglama ve nesne gomme(yerleshtirme). bir yazilim tarafindan olushturulan bir nesnenin ozelliklerini kaybetmeden bashka bir yazilim tarafindan kullanilabilmesini saglar. bu tur nesneler uzerinde deishiklik yapmak istenirse nesne uzerinden orjinal yazilima baglanmak olanaklidir.

object linking and embedding kisaltmasidir turkcesi ise nesne baglama ve gömme olarak cevrile bilir microsoft office uygulamaları arasında verialı$veri$ini mümkün kılan teklojinin adıdır.ole'nin 2 farkli boyutta islem gormektedir.bunlar baglama ve gömme ne demek simdi bu derseniz sole ki excelde bi islem yaptınız worldbelgesine transferini yapmayı dusunuyorsunuz iste bu hadise bunu mumkun kılmaktadır.

Demek ki bizim bir nesnemiz var ve ondan bir örnek yaratıp, örneğimiz üzerinden işlemler yapmak istiyoruz.

Peki buradaki OLE nesnemiz olan Msxml2.ServerXMLHTTP.6.0 kimdir?

Önce MSXML'den başlayalım. Microsoft XML Core Services (MSXML) W3C uyumlu XML API leri ile yüksek performanslı XML temelli uygulamalar geliştirmeye yarar. Bu kısım biraz genişçe devam edebilir ama konumuzdan sapmayacağım. Neydi konumuz Fiddler ile SQL Server üstünden yaptığımız Web Servisi çağrılarını görüntülemek.
Sırada bu örneği yaratırken kullandığımız INT tipinde @hr ve @Request değişkenleri. @hr sayesinde bu örnekleme işimiz eğer 0 dan başka bir sonuç gelmişse HATA olarak değerlendirecek ve hatayı görüntülemek için IF @hr <> 0 satırını kullanacağız. Burada detaylandırılacak bir şey varsa ben bilmiyorum. Gelin ekran çıktılarına bakalım:

Peki BAŞARISIZ bir örneklendirmeye bakalım:

Açıktırki örneklendiremememiz makinede olmayan bir OLE nesnesini kullanmak arzumuzdan.
Msxml2.ServerXMLHTTP.6.0 OLE nesnesi sistemimizde kayıtlıyken

Msxml2.ServerXMLHTTP.5.0 Registry'de kayıtlı değil.
Sorgulamak için registry sorgusu da deneyebilirsiniz:
C:\>reg query hkcr /f xmlhttp

HKEY_CLASSES_ROOT\Microsoft.XMLHTTP
HKEY_CLASSES_ROOT\Microsoft.XMLHTTP.1.0
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP.3.0
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP.4.0
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP.6.0
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP.3.0
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP.4.0
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP.6.0
End of search: 10 match(es) found.

C:\>

Ayrıca OLE nesnelerimizi ProgId ya da ClsId ile çağırabiliriz

Peki CLS Id nedir?

Ya ProgId?

OLE nesnelerimizi eğer CLS ID leri ile yaratmak istersek önce CLS ID lerini nerede bulabileceğimize bakalım:

Ve şimdide CLS ID ile SQL içinde örnekleme işine bakalım:

Devamını yazacağım ama önce Verdi nin konserine gitmeliyim. Yarın devam ederim ;)

Bir Verdi Konseri harikaydı...

Fiddler SQL'i nasıl dinler

Normalde dinlemesini bekleriz ama Fiddler'e düşmez SQL web servis çağrılarınız. SQL Server sizin login olduğunuz oturum üstünden çalışmadığı için Fiddler görüntüleyemeyecektir.
Aşağıda nasıl yapacağımızı görelim:
Artık fiddler sql web service çağrılarını görebileceksiniz.

Neden tüm web servis çağrılarım Fiddler'e düşmüyor

Önce düşen web servis sonuçları var ve düşmeyen var. O halde sorunu tespit için fiddlere baktım ve http talebinin sonuçlarının boyutundan şüphelendim. Bunu test etmek için dönen cevabın boyutunu ayarlayabileceğim bir site buldum. Url adresinden dönecek sonucun boyutunu değiştirebilirsiniz https://www.random.org/cgi-bin/randbyte?nbytes=1324&format=h ve fiddler üstünde görebiliyorsunuz.
SQL kodumuzla çağrı yapalım ve sonucu SQL tarafından alınamayan durumu inceleyelim:
DECLARE @Request INT,
  @hr INT,
  @activeX VARCHAR(50) = 'Msxml2.ServerXMLHTTP.6.0';
  SET @activeX = '{88d96a0b-f192-11d4-a65f-0040963251e5}';

EXEC @hr = sp_OACreate @activeX, @Request OUT;
EXEC sp_OAMethod @Request, 'open', NULL, 'GET','https://www.random.org/cgi-bin/randbyte?nbytes=1307&format=h', 'false'
EXEC sp_OAMethod @Request, 'send', null, ''

DECLARE @ResponseText Varchar(4000)
EXEC sp_OAMethod @Request, 'responseText', @ResponseText OUTPUT
SELECT @ResponseText as Response
Exec sp_OADestroy @Request
 
IF @hr <> 0
BEGIN
   DECLARE @src varchar(255), @desc varchar(255)
   EXEC sp_OAGetErrorInfo @Request, @src OUT, @desc OUT 
   SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
   RETURN
END
ELSE
 Exec sp_OADestroy @Request

Bu kezde başarılı bir web sayfası çağrısını SQL'den yapalım:

Peki Sorun OLE Nesnesinde mi?

SQL'de göremiyoruz ama arada OLE nesnemiz var acaba sorun onda mı? OLE nesnemizin çektiği sonucu bir dosyaya yazalım ve görelim gelen cevabı kesiyor ya da kırpıyormu.
Test için yine fiddler ve OLE nesnemizden örneğimizi yazıp konsoldan çalıştırmak için bir script dosyası oluşturalım.
Dim oXMLHTTP
Dim oStream

Set oXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")

Dim byteSize 
byteSize="1306"

oXMLHTTP.Open "GET", "https://www.random.org/cgi-bin/randbyte?nbytes="+byteSize+"&format=h", False
oXMLHTTP.Send

If oXMLHTTP.Status = 200 Then
 Wscript.Echo oXMLHTTP.responseBody
 Set oStream = CreateObject("ADODB.Stream")
 oStream.Open
 oStream.Type = 1
 oStream.Write oXMLHTTP.responseBody
 oStream.SaveToFile "c:\temp\sonuc"+byteSize+".txt"
 oStream.Close
End If
Yukarıdaki kodumuzun çalışması için MSXML nin internet explorer->internet options -> Security Settings -> Custom Level -> Access data sources accross domains -> Enable ayarının yapılması gerekecek:

4000 altındaki cevapları SQL içinde görebildiğimiz için öncelikle bunu dosyaya yazdırabiliyor muyuz diye bakalım:

SQL'e yazdıramadığımız sonucu bakalım dosyaya yazabilecek miyiz ve acaba OLE nesnemiz mi SQL'e aktarmıyor diye kontrol edelim:
Geldiğimiz noktada sorun sp_OACreate 'in NVarchar(4000) limitine takılmamızmış :) Öğrendiğim adres ve çözmek isterseniz çözümleri için buraya veya buraya tıklayabilirsiniz.

Bu noktadan sonra ben .Net assemblysi yazarak ilgili fonksiyonlarını çağırmayı tercih edeceğim :)

Azim ve bilgi dolu okumalar olsun....