【问题标题】:Perform http request with a connection to specified IP address通过连接到指定 IP 地址执行 http 请求
【发布时间】:2022-10-25 10:39:53
【问题描述】:

我正在尝试编写一个函数来验证负载均衡器后面的 Web 服务器。因此,我需要连接到未在 DNS 中注册的 IP 地址,因为 DNS 将注册到负载平衡器的前端 IP 地址。其他建议是使用“https://192.168.1.17/”之类的内容并忽略证书错误,但我需要在此过程中验证证书。我相信最好的选择是使用连接回调方法,但我无法得到接近工作的东西。

这是我的一次尝试中的代码 sn-p。

$SourceUri = [System.Uri]::New("https://site.domain.com/healthCheck")
[System.Net.IPAddress]$IPAddress = '192.168.1.17'
[int]$Port = 443

$SocketsHttpHandler = [System.Net.Http.SocketsHttpHandler]::New()
$SocketsHttpHandler.ConnectCallback = function:{
    param([System.Net.IPAddress]$IPAddress, [int]$Port)

    $Socket = [System.Net.Sockets.Socket]::New([System.Net.Sockets.SocketType]::Stream, [System.Net.Sockets.ProtocolType]::Tcp)
    $Socket.NoDelay = $true
    $Socket.ConnectAsync($IPAddress, $Port)

    $NetworkStream = [System.Net.Sockets.NetworkStream]::New($Socket, $true)
    return $NetworkStream
}

$HttpClient = [System.Net.Http.HttpClient]::New($SocketsHttpHandler($IPAddress, $Port))
$task = $HttpClient.GetStringAsync($SourceUri)
$task.wait()
if ($task.IsCompleted) {
    Write-Output $task.Result
} else {
    Write-Output "Something went wrong: " + $task.Exception.Message
}

请让我知道我应该怎么做才能使回调方法正常工作。谢谢你。

更新我想我取得了一些进步,但收到设置回调的错误。

$SourceUri = [System.Uri]::New("https://site.domain.com/healthCheck")
[System.Net.IPAddress]$IPAddress = '192.168.1.17'
[int]$Port = 443

$Code = @'
using System;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

public sealed class SocketCallbackClosure
{
    public IPAddress IPAddress { get; }
    public int Port { get; }

    public Func<SocketsHttpConnectionContext, CancellationToken, Task<NetworkStream>> Callback { get; }

    public SocketCallbackClosure(IPAddress IPAddress, int Port)
    {
        this.IPAddress = IPAddress;
        this.Port = Port;

        this.Callback = CallbackImpl;
    }

    private async Task<NetworkStream> CallbackImpl(
        SocketsHttpConnectionContext ConnectionContext,
        CancellationToken CToken)
    {
        var s = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };

        try
        {
            s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, 5);
            s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 5);
            s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, 5);

            await s.ConnectAsync(this.IPAddress, this.Port, CToken);

            return new NetworkStream(s, ownsSocket: true);
        }
        catch
        {
            s.Dispose();
            throw;
        }
    }
}
'@

Add-Type -TypeDefinition $Code

$SocketCallbackClosure = [SocketCallbackClosure]::New($IPAddress, $Port)

$SocketsHttpHandler = [System.Net.Http.SocketsHttpHandler]::New()
$SocketsHttpHandler.ConnectCallback = $SocketCallbackClosure.Callback

$HttpClient = [System.Net.Http.HttpClient]::New($SocketsHttpHandler)
$task = $HttpClient.GetStringAsync($SourceUri)
$task.wait()
if ($task.IsCompleted) {
    Write-Output $task.Result
} else {
    Write-Output "Something went wrong: " + $task.Exception.Message
}

【问题讨论】:

  • 尝试使用 C# 或其他语言查找解决方案,然后将其转换为 PowerShell。

标签: powershell


【解决方案1】:

PowerShell 中似乎存在不允许设置回调的限制或错误。我能够通过在类型定义的代码中移动回调来解决。请参阅下面的代码。

$Uri = [System.Uri]::New("https://site.domain.com/healthCheck")
[System.Net.IPAddress]$IPAddress = '192.168.1.17'
[int]$Port = 443

$TypeDefinition = @'
using System;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;

public class HttpClientHandlers
{
    public static HttpClient GetHttpClient(IPAddress IPAddress, int Port)
    {
        if (IPAddress.Any.Equals(IPAddress))
            return new HttpClient();

        SocketsHttpHandler HttpHandler = new SocketsHttpHandler();

        HttpHandler.ConnectCallback = async (context, cancellationToken) =>
        {
            var s = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };

            try
            {
                s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, 5);
                s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 5);
                s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveRetryCount, 5);

                await s.ConnectAsync(IPAddress, Port, cancellationToken);

                return new NetworkStream(s, ownsSocket: true);
            }
            catch
            {
                s.Dispose();

                throw;
            }
        };

        return new HttpClient(HttpHandler);
    }
}
'@

Add-Type -TypeDefinition $TypeDefinition

$HttpClient = [HttpClientHandlers]::GetHttpClient($IPAddress, $Port)

$Task = $HttpClient.GetAsync($Uri)

while ($Task.IsCompleted -eq $false) {
    Start-Sleep -Milliseconds 100
}

if ($Task.IsCompletedSuccessfully) {
    Write-Output $task.Result
} else {
    Write-Output "Something went wrong: " + $task.Exception.Message
}

【讨论】:

    猜你喜欢
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 2010-11-13
    • 2018-09-15
    • 2020-05-08
    • 1970-01-01
    相关资源
    最近更新 更多