2013-07-01 21 views
7

Chciałem wysłać żądanie HTTP z serwera SQL do serwera Tomcat. Zainstalowałem aplikację SQL Express 2012 Express i inną .NET na serwerze Tomcat. Przeszedłem przez to jak Make a HTTP request from SQL server Jak mogę utworzyć żądanie HTTP z serwera SQL?

Jak napisano w powyższym artykule, "Obiekt COM WinHttp.WinHttpRequest.5.1 musi być zainstalowany na serwerze, niektóre typowe odmiany to WinHttp.WinHttpRequest.5". Pobrałem winhttp.zip z winhttp download link, znalazłem plik winhttp.dll w folderze zip i wkleiłem go w C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2\MSSQL\Binn, jak zasugerowano w tym msdn link.

następstwie tej samej rady, mam wykonany następujący wiersz w SSMS:

sp_addextendedproc 'GetHttp', 
'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2\MSSQL\Binn\winhttp.dll'; 

I wykonany również następujący kod w SSMS jak powiedział w „Złóż żądania HTTP z łącza serwera SQL”:

Alter function GetHttp 
(
@url varchar(8000)  
) 
returns varchar(8000) 
as 
BEGIN 
DECLARE @win int 
DECLARE @hr int 
DECLARE @text varchar(8000) 

EXEC @hr=sp_OACreate 'WinHttp.WinHttpRequest.5.1',@win OUT 
IF @hr <> 0 EXEC sp_OAGetErrorInfo @win 

EXEC @hr=sp_OAMethod @win, 'Open',NULL,'GET',@url,'false' 
IF @hr <> 0 EXEC sp_OAGetErrorInfo @win 

EXEC @hr=sp_OAMethod @win,'Send' 
IF @hr <> 0 EXEC sp_OAGetErrorInfo @win 

EXEC @hr=sp_OAGetProperty @win,'ResponseText',@text OUTPUT 
IF @hr <> 0 EXEC sp_OAGetErrorInfo @win 

EXEC @hr=sp_OADestroy @win 
IF @hr <> 0 EXEC sp_OAGetErrorInfo @win 

RETURN @text 
END 

Następnie pojawia się błąd

Msg 2010, Level 16, State 1, Procedura GetHttp, Linia 2
Nie można wykonać zmiany na "GetHttp", ponieważ jest to niezgodny typ obiektu.

Nie mam pojęcia, jak wywołać funkcję wysyłania żądania HTTP. Zakładam, że jest to coś takiego: GetHttp('http://www.google.co.in/').

Czego mi brakuje?

+13

Nie. Po prostu nie rób tego. Nie jest to przeznaczenie SQL Server. –

+8

To jest klasyczny "kiedy masz młotek, wszystko co widzisz to gwoździe", NIE rób tego – SQLMenace

+0

@ Mladen Prajdic moim wymaganiem jest, że istnieją dwie różne bazy danych na różnych serwerach (A i B) i jedna aplikacja serwera tomcat . Jeśli jest jakakolwiek modyfikacja w DB A, to wysyła żądanie http do aplikacji serwera tomcat, aplikacja na serwerze tomcat wykonuje obliczenia i zapisuje dane w DB B. Tak więc muszę wywołać aplikację tylko z serwera sql, ponieważ użytkownik nie ma dostępu do aplikacji serwera tomcat. – niren

Odpowiedz

4

Dostałem odpowiedź od powershell. To, co zrobiłem, to open powershell na serwerze sql, a następnie wykonałem następujący kod w powershell.

$http_Request= New-Object system.Net.WebClient; 
$Result = $http_Request.downloadString("url") 
+4

Jak wykonać ten skrypt w sp_procedure? –

8

Dostałem kolejną odpowiedź. I stworzył procedurę jak następuje

CREATE procedure HTTP_Request(@sUrl varchar(200)) 
As 


Declare 
@obj int 
,@hr int 
,@msg varchar(255) 


exec @hr = sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT 
if @hr <> 0 begin Raiserror('sp_OACreate MSXML2.ServerXMLHttp.3.0 
failed', 16,1) return end 


exec @hr = sp_OAMethod @obj, 'open', NULL, 'POST', @sUrl, false 
if @hr <>0 begin set @msg = 'sp_OAMethod Open failed' goto eh end 


exec @hr = sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Type', 
'application/x-www-form-urlencoded' 
if @hr <>0 begin set @msg = 'sp_OAMethod setRequestHeader failed' goto 
eh end 


exec @hr = sp_OAMethod @obj, send, NULL, '' 
if @hr <>0 begin set @msg = 'sp_OAMethod Send failed' goto eh end 

exec @hr = sp_OADestroy @obj 
return 
eh: 
exec @hr = sp_OADestroy @obj 
Raiserror(@msg, 16, 1) 
return 
GO 

Zadzwoniłem procedurę przechowywaną z url

USE [master] 
GO 

DECLARE @return_value int 

EXEC @return_value = [dbo].[HTTP_Request] 
    @sUrl = N'url' 

SELECT 'Return Value' = @return_value 

GO 

Dziękujemy wam, aby mnie to działa.

+0

Otrzymałem komunikat "SQL Server zablokował dostęp do procedury" sys.sp_Otwórz "składnika" Procedury automatyzacji Ole ", ponieważ ten komponent jest wyłączony jako część konfiguracji bezpieczeństwa dla tego serwera." –

+0

Ten link powinien pomóc Ci przejść przez zablokowany dostęp do błędu procedury. http://sqlsolace.blogspot.com/2009/09/sql-server-blocked-access-to-procedure.html –

+0

Zwraca 0, ale mój api reszta zwrócił json ... –

1

To naprawdę pomogło mi @niren.

Myślałem, że dodam moją poprawkę, która umieszcza ją w funkcji skalarnej i pozwala uzyskać odpowiedź usługi. Jedynym minusem są funkcje skalarne, których nie można przebić, więc jest coś do myślenia o łapaniu gdzie indziej.

CREATE function [dbo].[fn_HttpPOST] 
(
    @sUrl varchar(8000)  
) 
returns varchar(8000) 
as 
BEGIN 
    DECLARE @obj int 
    DECLARE @hr int 
    DECLARE @msg varchar(8000)  


    exec @hr = sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT 
    if @hr <> 0 begin set @Msg = 'sp_OACreate MSXML2.ServerXMLHttp.3.0 failed' return @Msg end 

    exec @hr = sp_OAMethod @obj, 'open', NULL, 'POST', @sUrl, false 
    if @hr <>0 begin set @msg = 'sp_OAMethod Open failed' goto eh end 

    exec @hr = sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded' 
    if @hr <>0 begin set @msg = 'sp_OAMethod setRequestHeader failed' goto eh end 

    exec @hr = sp_OAMethod @obj, send, NULL, '' 
    if @hr <>0 begin set @msg = 'sp_OAMethod Send failed' goto eh end 

    EXEC @hr=sp_OAGetProperty @Obj,'ResponseText',@msg OUTPUT 
    IF @hr <> 0 EXEC sp_OAGetErrorInfo @Obj 

    exec @hr = sp_OADestroy @obj 

    RETURN @msg 

    eh: 
    exec @hr = sp_OADestroy @obj 
    return @msg 
END 
1

Wykonane tego potwora na własne potrzeby

CREATE PROCEDURE [dbo].[RequestHttpWebService] 
    @Url varchar(1024), 
    @HttpMethod varchar(10), 
    @ParamsValues varchar(1024), -- param1=value&param2=value 
    @SoapAction varchar(1024) = null 
AS 
BEGIN 
    SET NOCOUNT ON; 

    if @HttpMethod in ('get','GET') and len(@ParamsValues) > 0 
    begin 
     set @Url = @Url + '?' + @ParamsValues 
    end 

    declare @obj int 
     ,@response varchar(8000) 
     ,@responseXml xml 
     ,@status varchar(50) 
     ,@statusText varchar(1024) 
     ,@method varchar(10) = (case when @HttpMethod in ('soap','SOAP') then 'POST' else @HttpMethod end) 

    exec sp_OACreate 'MSXML2.ServerXMLHttp', @obj out 
    exec sp_OAMethod @obj, 'Open', null, @method, @Url, false 

    if @HttpMethod in ('get','GET') 
    begin 
     exec sp_OAMethod @obj, 'send' 
    end 
    else if @HttpMethod in ('post','POST') 
    begin 
     exec sp_OAMethod @obj, 'setRequestHeader', null, 'Content-Type', 'application/x-www-form-urlencoded' 
     exec sp_OAMethod @obj, 'send', null, @ParamsValues 
    end 
    else if @HttpMethod in ('soap','SOAP') 
    begin 
     if @SoapAction is null 
      raiserror('@SoapAction is null', 10, 1) 

     declare @host varchar(1024) = @Url 
     if @host like 'http://%' 
      set @host = right(@host, len(@host) - 7) 
     else if @host like 'https://%' 
      set @host = right(@host, len(@host) - 8) 

     if charindex(':', @host) > 0 and charindex(':', @host) < charindex('/', @host) 
      set @host = left(@host, charindex(':', @host) - 1) 
     else 
      set @host = left(@host, charindex('/', @host) - 1) 

     declare @envelope varchar(8000) = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><{action} xmlns="http://tempuri.org/">{params}</{action}></soap:Body></soap:Envelope>' 
     declare @params varchar(8000) = '' 

     WHILE LEN(@ParamsValues) > 0 
     BEGIN 
      declare @param varchar(256), 
        @value varchar(256) 

      IF charindex('&', @ParamsValues) > 0 
      BEGIN 

       SET @param = left(@ParamsValues, charindex('&', @ParamsValues) - 1) 
       set @value = RIGHT(@param, len(@param) - charindex('=', @param)) 
       set @param = left(@param, charindex('=', @param) - 1) 
       set @params = @params + '<' + @param + '>' + @value + '</'+ @param + '>' 
       SET @ParamsValues = right(@ParamsValues, LEN(@ParamsValues) - LEN(@param + '=' + @value + '&')) 
      END 
      ELSE 
      BEGIN 
       set @value = RIGHT(@ParamsValues, len(@ParamsValues) - charindex('=', @ParamsValues)) 
       set @param = left(@ParamsValues, charindex('=', @ParamsValues) - 1) 

       set @params = @params + '<' + @param + '>' + @value + '</'+ @param + '>' 
       SET @ParamsValues = NULL 
      END 
     END 

     set @envelope = replace(@envelope, '{action}', @SoapAction) 
     set @envelope = replace(@envelope, '{params}', @params) 

     set @SoapAction = 'http://tempuri.org/' + @SoapAction 

     print @host 
     print @SoapAction 
     print @envelope 

     exec sp_OAMethod @obj, 'setRequestHeader', null, 'Content-Type', 'text/xml; charset=utf-8' 
     exec sp_OAMethod @obj, 'setRequestHeader', null, 'Host', @host 
     exec sp_OAMethod @obj, 'setRequestHeader', null, 'SOAPAction', @SoapAction 
     exec sp_OAMethod @obj, 'send', null, @envelope 
    end 

    exec sp_OAGetProperty @obj, 'responseText', @response out 
    exec sp_OADestroy @obj 

    select @status as [status], @statusText as [statusText], @response as [response] 

END 

GO 
+0

To robi http, ale zawsze return 0 –

Powiązane problemy