Как я могу сделать HTTP-запрос с SQL-сервера?

Я хотел отправить HTTP-запрос с сервера SQL на сервер Tomcat. Я установил приложение SQL Express 2012 Express и не .NET на сервере Tomcat. Я прошел через это как Сделать HTTP-запрос с SQL-сервера

Как сказано в этой статье, "COM-объект WinHttp.WinHttpRequest.5.1 должен быть установлен на сервере, некоторые типичные варианты - WinHttp.WinHttpRequest.5".  Я загрузил winhttp.zip из winhttp download link, нашел winhttp.dll в папке zip и вставил его в C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER2\MSSQL\Binn, как предложено в этом ссылка msdn.

Следуя тому же совету, я выполнил следующую строку в SSMS:

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

Я также выполнил следующий код в SSMS, как сказано в "Сделать HTTP-запрос из ссылки SQL Server":

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

Затем я получаю ошибку

Msg 2010, уровень 16, состояние 1, процедура GetHttp, строка 2
Невозможно выполнить изменение в 'GetHttp', потому что это несовместимый тип объекта.

Я не знаю, как вызвать функцию отправки HTTP-запроса. Я предполагаю, что это что-то вроде этого GetHttp('http://www.google.co.in/').

Что мне не хватает?

Ответ 1

Я получил ответ от powershell. Что я сделал - это open powershell в sql-сервере, тогда я выполнил следующий код в powershell.

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

Ответ 2

Я получил еще один ответ. Я создал процедуру, как следует

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

Я вызвал хранимую процедуру с url

USE [master]
GO

 DECLARE    @return_value int

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

SELECT  'Return Value' = @return_value

GO

Спасибо, ребята, чтобы заставить меня работать.

Ответ 3

Это действительно помогло мне @niren.

Думаю, что я опубликую свою поправку, которая помещает ее в скалярную функцию и позволяет получить ответ службы. Единственный недостаток - это скалярные функции, которые не могут использовать рейзерроры, поэтому есть что подумать о том, чтобы поймать в другом месте.

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

Ответ 4

Сделал этот монстр для моих собственных нужд

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

Ответ 5

screenshot

Наиболее гибкий подход здесь заключается в использовании пользовательской функции CLR, которую вы можете просто определить в С# следующим образом:

[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
    var wc = new WebClient();
    var html = wc.DownloadString(url.Value);
    return new SqlString (html);
}

Полная инструкция по установке здесь - https://github.com/infiniteloopltd/SQLHttp

Ответ 6

правильный способ - создать CLR, который будет содержать код С# для отправки запроса http/s, поскольку мы хотим избежать утечек памяти и проблем с безопасностью, которые могут возникнуть при использовании старого способа, такого как sp_OACreate.

например:   evar request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx"); var postData = "thing1=hello"; postData += "&amp;amp;amp;amp;amp;thing2=world"; var data = Encoding.ASCII.GetBytes(postData); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } var response = (HttpWebResponse)request.GetResponse(); var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

использование sp_OACreate менее безопасно, в то время как CLR может быть подписан и проверен вами.