Я следовал документации GitHub для реализации http-запросов с расширением CURL, работы в SQL Server 2008 R2, Visual Studio 2010 и .NET 3.5.
Мне удалось скомпилировать и правильно подписать .dll в Visual Studio, чтобы затем создать схемы и функции в SQL Server, так как все работает правильно, однако я могу выполнить GET и POST из SQL Server, однако, когда я хочу выполнить ПОЛУЧИТЬ или POST в SABA API, он генерирует серию ошибок.
Ошибка .NET Framework при выполнении пользовательского задания
подпрограмма или агрегат "XGET": System.Net.WebException: базовый
соединение было закрыто: при отправке произошла непредвиденная ошибка. --->
System.IO.IOException: получил неожиданный EOF или 0 байтов от
транспортный поток. System.IO.IOException: в
System.Net.FixedSizeReader.ReadPacket (буфер Byte [], смещение Int32,
Количество Int32) в System.Net.Security.SslState.StartReadFrame (Byte []
буфер, Int32 readBytes, AsyncProtocolRequest asyncRequest) в
System.Net.Security.SslState.StartReceiveBlob (буфер Byte [],
AsyncProtocolRequest asyncRequest) в
System.Net.Security.SslState.CheckCompletionBeforatextReceive (ProtocolTokat
сообщение, AsyncProtocolRequest asyncRequest) в
System.Net.Security.SslState.StartSatdBlob (Byte [] входящий, Int32
считать, AsyncProtocolRequest asyncRequest) в
System.Net.Security.SslState.ForceAuthattication (логическое значение receiveFirst,
Байт [] буфер, AsyncProtocolRequest asyncRequest) в
System.Net.Security.SslState.ProcessAuthattication (LazyAsyncResult
lazyResult) в
System.Net.TlsStream.CallProcessAuthattication (состояние объекта) в
System.Threading.ExecutionContext.runTryCode (Object userData) в
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup (TryCode
код, CleanupCode backoutCode, Object userData) в
System.Threading.ExecutionContext.RunInternal (ExecutionContext
executeContext, обратный вызов ContextCallback, состояние объекта) в
System.Threading.ExecutionContext.Run (ExecutionContext
executeContext, обратный вызов ContextCallback, состояние объекта) в
System.Net.TlsStream.ProcessAuthattication (результат LazyAsyncResult)
в System.Net.TlsStream.Write (буфер Byte [], смещение Int32, размер Int32)
в System.Net.PooledStream.Write (буфер Byte [], смещение Int32, Int32).
размер) в System.Net.ConnectStream.WriteHeaders (Boo ...
System.Net.WebException: в
System.Net.WebCliatt.DownloadDataInternal (адрес Uri, веб-запрос &
запрос) в System.Net.WebCliatt.DownloadString (адрес Uri) ...
Это код сборки
using Microsoft.SqlServer.Server;
using System;
using System.Data.SqlTypes;
using System.Net;
using System.Threading;
public static class Curl
{
[SqlFunction]
[return: SqlFacet(MaxSize = -1)]
public static SqlChars Get(SqlChars H, SqlChars url)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
var client = new WebClient();
AddHeader(H, client);
return new SqlChars(
client.DownloadString(
Uri.EscapeUriString(url.ToSqlString().Value)
).ToCharArray());
}
[SqlProcedure]
public static void Post(SqlChars H, SqlChars d, SqlChars url)
{
var client = new WebClient();
AddHeader(H, client);
if (d.IsNull)
throw new ArgumentException("You must specify data that will be sent to the endpoint", "@d");
var response =
client.UploadString(
Uri.EscapeUriString(url.ToSqlString().Value),
d.ToSqlString().Value
);
SqlContext.Pipe.Send("Request is executed. " + response);
}
[SqlProcedure]
public static void PostWithRetry(SqlChars H, SqlChars d, SqlChars url)
{
var client = new WebClient();
AddHeader(H, client);
if (d.IsNull)
throw new ArgumentException("You must specify data that will be sent to the endpoint", "@d");
int i = RETRY_COUNT;
string response = "";
do try
{
response =
client.UploadString(
Uri.EscapeUriString(url.ToSqlString().Value),
d.ToSqlString().Value
);
i = -1;
break;
}
catch (Exception ex)
{
SqlContext.Pipe.Send("Error:\t" + ex.Message + ". Waiting " + DELAY_ON_ERROR + "ms.");
i--;
Thread.Sleep(DELAY_ON_ERROR);
}
while (i > 0);
if (i == -1)
SqlContext.Pipe.Send("Request is executed." + response);
}
static readonly int RETRY_COUNT = 3;
static readonly int DELAY_ON_ERROR = 50;
public static bool IsNullOrWhiteSpace(this string theString)
{
if (theString == null)
{
return false;
}
if (theString.Trim() == string.Empty)
{
return false;
}
return true;
}
private static void AddHeader(SqlChars H, WebClient client)
{
if (!H.IsNull)
{
string header = H.ToString();
if (!IsNullOrWhiteSpace(header))
client.Headers.Add(HttpRequestHeader.UserAgent, header);
}
}
};
А это как использовать в SQL Query
declare @hkey nvarchar(4000) = 'SabaCertificate: 31336132353061666330315E235E756F6E6555E6261536974655E235E656E5F55535E235E536162615E235E24414021463393C69358BE384802BA1BBEAD3B4661862F193021435F7E28A30F7540FE661B9C5F30FDB06C';
declare @endpoint nvarchar(1000) = 'https://libertad-api.sabacloud.com/v1/location?count=10&startPage=1';
select curl.xget(@hkey, @endpoint)
Я уже тестировал его в PostMan, вводя заголовок SabaCertificate, и, если он выдает мне результат, однако, если сертификат неверен, он также выдает ответ, и он не отображается.
Пример неверного запроса:
{"errorCode":123,"errorMessage":"Invalid or expired Certificate"}
Но это также не дает мне ответа об ошибке сертификата, которую я должен изменить в своем WebClient, чтобы это работало.
Я добавил, что сертификат слишком большой, потому что иногда я получаю эту ошибку:
Идентификатор, который начинается с 'SabaCertificate:
31336132353061666330315E235E756F6E6555E6261536974655E235E656E5F55535E235E536162615E235E24414021463393C69358BE384802BA1BBEAD3B4661862F193021435F7E28A30F7540FE661B9C5F30FDB06C»
слишком долго Максимальная длина 128.