System.Net.WebException: The operation has timed out at System.Net.HttpWebRequest.GetResponse()

解决WebRequest超时问题
本文探讨了WebRequest在获取响应时出现超时的原因,并提供了一种有效的解决方案,即使用using语句来确保WebResponse对象能被正确地关闭并释放连接,从而避免了连接池中的连接被长时间占用导致的超时。

System.Net.WebException: The operation has timed out  at System.Net.HttpWebRequest.GetResponse()

在请求获取响应结果的时候,超时,具体原因可能就是如下面Jon Skeet所说,

WebResponse implements IDisposable,
so you should use a using statement for it (and for the StreamReader you create from the stream).
If you leave a WebResponse open, it will take up a connection from the connection pool to that host,
and you can end up with timeouts this way.
WebResponse继承IDisposable接口,会释放非托管资源
所以你需要使用声明来创建资源对象
如果你打开WebResponse资源响应,那么他将通过连接池连接主机,使用这个方式,超时将不会成为问题。
应该是这么翻译吧╮(╯_╰)╭

This will close the stream and the response even if an exception is thrown, 
so you'll always clean up the resources (in this case releasing the connection back to the pool) promptly.
这个将会关闭stream和response,即使出现抛出异常的情况
所以你总能够即时清理好资源(释放应用池的连接)

这个方式,尝试了一下,暂时没出现什么问题,算解决了99%吧,等到以后再出现什么问题,再来看。

下面是网上找到的一个解决方案:

http://stackoverflow.com/questions/15493321/system-net-webexception-the-operation-has-timed-out-on-httpwebresponse

Author:Jon Skeet

System.Net.WebException: The operation has timed out on HttpWebResponse

This may well be the problem:

HttpWebResponse myResp = (HttpWebResponse)myReq.GetResponse();

WebResponse implements IDisposable, so you should use a using statement for it (and for the StreamReader you create from the stream). If you leave a WebResponse open, it will take up a connection from the connection pool to that host, and you can end up with timeouts this way. The fixed code would look like this:

string responseString;
using (var response = myReq.GetResponse())
{
    using (var reader = new StreamReader(response.GetResponseStream())
    {
        responseString = reader.ReadToEnd();
    }
}

This will close the stream and the response even if an exception is thrown, so you'll always clean up the resources (in this case releasing the connection back to the pool) promptly.

 

PS C:\Users\Administrator> # 加载必要程序集(兼容 .NET 9 和旧版) PS C:\Users\Administrator> try { >> Add-Type -AssemblyName System.Net.Http -ErrorAction Stop >> } catch { >> [System.Reflection.Assembly]::LoadWithPartialName("System.Net.Http") | Out-Null >> } >> PS C:\Users\Administrator> # 检测 .NET 版本 PS C:\Users\Administrator> $dotnetVersion = [System.Environment]::Version PS C:\Users\Administrator> $isNet9OrNewer = $dotnetVersion.Major -ge 9 -or ($dotnetVersion.Major -eq 8 -and $dotnetVersion.Minor -ge 0) PS C:\Users\Administrator> PS C:\Users\Administrator> function Invoke-EnhancedCurlRequest { >> [CmdletBinding()] >> param( >> [Parameter(Mandatory=$true)] >> [string]$Uri, >> [ValidateSet('GET','POST','PUT','DELETE','PATCH','HEAD','OPTIONS')] >> [string]$Method = 'GET', >> [hashtable]$Headers = @{}, >> [object]$Body, >> [int]$Timeout = 30, >> [switch]$SkipCertificateCheck, >> [switch]$UseGzipCompression, >> [switch]$EnableHttp2 >> ) >> >> # 修复1:使用强类型结果模板 >> $resultTemplate = [PSCustomObject]@{ >> StatusCode = 0 >> StatusMessage = "NotExecuted" >> Headers = [ordered]@{} >> Content = $null >> IsSuccess = $false >> Technology = "None" >> ErrorMessage = $null >> ElapsedMs = 0 >> Protocol = "Unknown" >> DotnetVersion = $dotnetVersion.ToString() >> } >> >> $timer = [System.Diagnostics.Stopwatch]::StartNew() >> $result = $resultTemplate.PSObject.Copy() >> >> # 修复2:重构证书检测逻辑 >> $useHttpClient = $true >> $oldCallback = $null >> >> if ($SkipCertificateCheck) { >> try { >> # 正确的证书验证检测方式 >> $testHandler = New-Object System.Net.Http.HttpClientHandler >> $testHandler.ServerCertificateCustomValidationCallback = { >> param($sender, $cert, $chain, $errors) >> return $true >> } >> } catch { >> $useHttpClient = $false >> } >> } >> >> if ($useHttpClient) { >> # ======================== .NET 9 优化实现 ======================== >> $result.Technology = "HttpClient(.NET $($dotnetVersion.Major))" >> >> try { >> # 创建 HttpClientHandler >> $handler = New-Object System.Net.Http.HttpClientHandler >> >> # .NET 9 特有的优化特性 >> if ($isNet9OrNewer) { >> # 启用 HTTP/2 或 HTTP/3 >> $handler.MaxConnectionsPerServer = 10 >> $handler.PooledConnectionLifetime = [System.TimeSpan]::FromMinutes(1) >> >> if ($EnableHttp2) { >> $handler.DefaultVersionPolicy = [System.Net.Http.HttpVersionPolicy]::RequestVersionOrHigher >> $handler.DefaultRequestVersion = [System.Version]::new(2, 0) >> } >> } >> >> # 证书验证 >> if ($SkipCertificateCheck) { >> $handler.ServerCertificateCustomValidationCallback = { >> param($sender, $cert, $chain, $errors) >> return $true >> } >> } >> >> # 压缩支持 >> if ($UseGzipCompression) { >> $handler.AutomaticDecompression = [System.Net.DecompressionMethods]::GZip >> } >> >> # 创建 HttpClient >> $client = New-Object System.Net.Http.HttpClient($handler) >> $client.Timeout = [System.TimeSpan]::FromSeconds($Timeout) >> >> # 修复3:正确创建HttpMethod对象 >> $httpMethod = [System.Net.Http.HttpMethod]::new($Method) >> $request = New-Object System.Net.Http.HttpRequestMessage($httpMethod, $Uri) >> >> # 协议版本设置 >> if ($isNet9OrNewer -and $EnableHttp2) { >> $request.Version = [System.Version]::new(2, 0) >> $request.VersionPolicy = [System.Net.Http.HttpVersionPolicy]::RequestVersionOrHigher >> } >> >> # 添加默认 User-Agent >> if (-not $Headers.ContainsKey('User-Agent')) { >> $request.Headers.TryAddWithoutValidation("User-Agent", "PowerShell-HTTPClient/1.0 (.NET $($dotnetVersion.Major))") >> } >> >> # 添加自定义头 >> foreach ($key in $Headers.Keys) { >> if (-not $request.Headers.TryAddWithoutValidation($key, $Headers[$key])) { >> # 如果头字段无法添加到请求头,尝试添加到内容头 >> if (-not $request.Content) { >> $request.Content = New-Object System.Net.Http.StringContent("") >> } >> $request.Content.Headers.TryAddWithoutValidation($key, $Headers[$key]) >> } >> } >> >> # 处理请求体 >> if ($Body -and @('POST','PUT','PATCH') -contains $Method) { >> if ($Body -is [byte[]]) { >> $request.Content = New-Object System.Net.Http.ByteArrayContent($Body) >> } >> elseif ($Body -is [hashtable] -or $Body -is [System.Collections.IDictionary]) { >> $jsonBody = $Body | ConvertTo-Json -Depth 10 -Compress >> $request.Content = New-Object System.Net.Http.StringContent( >> $jsonBody, >> [System.Text.Encoding]::UTF8, >> "application/json" >> ) >> } >> elseif ($Body -is [string]) { >> $request.Content = New-Object System.Net.Http.StringContent( >> $Body, >> [System.Text.Encoding]::UTF8 >> ) >> } >> else { >> throw "Unsupported body type: $($Body.GetType().Name)" >> } >> } >> >> # 发送请求(异步转同步) >> $response = $client.SendAsync($request).GetAwaiter().GetResult() >> >> # 记录实际使用的协议 >> $result.Protocol = "HTTP/" + $response.Version.ToString() >> >> # 解析响应 >> $result.StatusCode = [int]$response.StatusCode >> $result.StatusMessage = $response.ReasonPhrase >> $result.IsSuccess = $response.IsSuccessStatusCode >> >> # 处理响应头 >> $result.Headers = [ordered]@{} >> foreach ($header in $response.Headers) { >> $result.Headers[$header.Key] = $header.Value -join ", " >> } >> >> foreach ($header in $response.Content.Headers) { >> $result.Headers[$header.Key] = $header.Value -join ", " >> } >> >> # 读取响应内容 >> $result.Content = $response.Content.ReadAsStringAsync().GetAwaiter().GetResult() >> } >> catch [System.Threading.Tasks.TaskCanceledException] { >> $result.ErrorMessage = "Request timed out after $Timeout seconds" >> $result.StatusCode = 408 >> $result.StatusMessage = "Timeout" >> } >> catch [System.Net.Http.HttpRequestException] { >> # 增强的错误处理 >> $ex = $_.Exception >> $result.ErrorMessage = $ex.ToString() >> >> # 检查具体错误类型 >> $dnsError = $false >> $sslError = $false >> >> if ($isNet9OrNewer) { >> # .NET 9 提供更精确的错误类型 >> if ($ex.InnerException -is [System.Net.Sockets.SocketException]) { >> $dnsError = $true >> } >> elseif ($ex.InnerException -is [System.Security.Authentication.AuthenticationException]) { >> $sslError = $true >> } >> } else { >> # 旧版兼容性处理 >> $currentException = $ex >> while ($currentException -ne $null) { >> if ($currentException -is [System.Net.Sockets.SocketException]) { >> $dnsError = $true >> break >> } >> if ($currentException -is [System.Security.Authentication.AuthenticationException]) { >> $sslError = $true >> break >> } >> $currentException = $currentException.InnerException >> } >> } >> >> if ($dnsError) { >> $result.StatusCode = 0 >> $result.StatusMessage = "DNSResolutionFailed" >> } >> elseif ($sslError) { >> $result.StatusCode = 495 >> $result.StatusMessage = "SSLCertificateError" >> } >> else { >> $result.StatusCode = 500 >> $result.StatusMessage = "HttpRequestError" >> } >> } >> catch { >> $result.ErrorMessage = $_.Exception.ToString() >> $result.StatusCode = 500 >> $result.StatusMessage = "InternalError" >> } >> finally { >> # 释放资源 >> if ($response -is [System.IDisposable]) { $response.Dispose() } >> if ($request -is [System.IDisposable]) { $request.Dispose() } >> if ($client -is [System.IDisposable]) { $client.Dispose() } >> if ($handler -is [System.IDisposable]) { $handler.Dispose() } >> } >> } >> else { >> # ======================== 备用实现(兼容旧版) ======================== >> $result.Technology = "HttpWebRequest" >> >> try { >> # 设置全局证书验证回调 >> if ($SkipCertificateCheck) { >> $oldCallback = [System.Net.ServicePointManager]::ServerCertificateValidationCallback >> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { >> param($sender, $certificate, $chain, $sslPolicyErrors) >> return $true >> } >> } >> >> # 创建请求 >> $request = [System.Net.HttpWebRequest]::Create($Uri) >> $request.Method = $Method >> $request.Timeout = $Timeout * 1000 >> >> # 添加默认 User-Agent >> if (-not $Headers.ContainsKey('User-Agent')) { >> $request.UserAgent = "PowerShell-HTTPClient/1.0 (Legacy)" >> } >> >> # 添加自定义头 >> foreach ($key in $Headers.Keys) { >> $request.Headers.Add($key, $Headers[$key]) >> } >> >> # 处理请求体 >> if ($Body -and @('POST','PUT','PATCH') -contains $Method) { >> $request.ContentType = "application/json" >> $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes(($Body | ConvertTo-Json -Depth 10 -Compress)) >> $request.ContentLength = $bodyBytes.Length >> >> $requestStream = $request.GetRequestStream() >> $requestStream.Write($bodyBytes, 0, $bodyBytes.Length) >> $requestStream.Close() >> } >> >> # 发送请求并获取响应 >> $response = $request.GetResponse() >> $result.StatusCode = [int]$response.StatusCode >> $result.StatusMessage = $response.StatusDescription >> $result.IsSuccess = $result.StatusCode -ge 200 -and $result.StatusCode -lt 300 >> >> # 读取响应头 >> $result.Headers = [ordered]@{} >> foreach ($key in $response.Headers.AllKeys) { >> $result.Headers[$key] = $response.Headers[$key] >> } >> >> # 读取响应体 >> $responseStream = $response.GetResponseStream() >> $reader = New-Object System.IO.StreamReader($responseStream) >> $result.Content = $reader.ReadToEnd() >> $reader.Close() >> $response.Close() >> } >> catch [System.Net.WebException] { >> $ex = $_.Exception >> $result.ErrorMessage = $ex.ToString() >> >> if ($ex.Response -ne $null) { >> $httpResponse = $ex.Response >> $result.StatusCode = [int]$httpResponse.StatusCode >> $result.StatusMessage = $httpResponse.StatusDescription >> >> # 读取错误响应体 >> $errorStream = $httpResponse.GetResponseStream() >> $errorReader = New-Object System.IO.StreamReader($errorStream) >> $result.Content = $errorReader.ReadToEnd() >> $errorReader.Close() >> } >> else { >> # 检查具体错误类型 >> if ($ex.Status -eq [System.Net.WebExceptionStatus]::NameResolutionFailure) { >> $result.StatusCode = 0 >> $result.StatusMessage = "DNSResolutionFailed" >> } >> elseif ($ex.Status -eq [System.Net.WebExceptionStatus]::TrustFailure) { >> $result.StatusCode = 495 >> $result.StatusMessage = "SSLCertificateError" >> } >> elseif ($ex.Status -eq [System.Net.WebExceptionStatus]::Timeout) { >> $result.StatusCode = 408 >> $result.StatusMessage = "Timeout" >> } >> else { >> $result.StatusCode = 500 >> $result.StatusMessage = "WebException" >> } >> } >> } >> catch { >> $result.ErrorMessage = $_.Exception.ToString() >> $result.StatusCode = 500 >> $result.StatusMessage = "InternalError" >> } >> finally { >> # 恢复全局证书验证回调 >> if ($SkipCertificateCheck) { >> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $oldCallback >> } >> } >> } >> >> $timer.Stop() >> $result.ElapsedMs = $timer.ElapsedMilliseconds >> return $result >> } >> PS C:\Users\Administrator> # 导出模块成员 PS C:\Users\Administrator> Export-ModuleMember -Function Invoke-EnhancedCurlRequest Export-ModuleMember : 只能从模块内调用 Export-ModuleMember cmdlet。 所在位置 行:1 字符: 1 + Export-ModuleMember -Function Invoke-EnhancedCurlRequest + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : PermissionDenied: (:) [Export-ModuleMember], InvalidOperationException + FullyQualifiedErrorId : Modules_CanOnlyExecuteExportModuleMemberInsideAModule,Microsoft.PowerShell.Commands.Expo rtModuleMemberCommand
最新发布
08-17
PS C:\Users\Administrator> # 加载必要程序集 - 使用更兼容的方式 PS C:\Users\Administrator> try { >> Add-Type -AssemblyName System.Net.Http -ErrorAction Stop >> } catch { >> [System.Reflection.Assembly]::LoadWithPartialName("System.Net.Http") | Out-Null >> } >> PS C:\Users\Administrator> function Invoke-EnhancedCurlRequest { >> [CmdletBinding()] >> param( >> [Parameter(Mandatory=$true)] >> [string]$Uri, >> [ValidateSet('GET','POST','PUT','DELETE','PATCH','HEAD','OPTIONS')] >> [string]$Method = 'GET', >> [hashtable]$Headers = @{}, >> [object]$Body, >> [int]$Timeout = 30, >> [switch]$SkipCertificateCheck, >> [switch]$UseGzipCompression >> ) >> >> $resultTemplate = [PSCustomObject]@{ >> StatusCode = 0 >> StatusMessage = "NotExecuted" >> Headers = [ordered]@{} >> Content = $null >> IsSuccess = $false >> Technology = "None" >> ErrorMessage = $null >> ElapsedMs = 0 >> } >> >> $timer = [System.Diagnostics.Stopwatch]::StartNew() >> $result = $resultTemplate.PSObject.Copy() >> $result.Technology = "HttpClient" >> >> $handler = $null >> $client = $null >> $request = $null >> $response = $null >> $globalCallbackSet = $false >> $oldCallback = $null >> >> try { >> # 创建 HttpClientHandler >> $handler = New-Object System.Net.Http.HttpClientHandler >> >> # 修复证书验证 - 兼容所有环境 >> if ($SkipCertificateCheck) { >> try { >> # 方法1:使用内置属性(.NET Core/.NET 5+) >> $handler.ServerCertificateCustomValidationCallback = { >> param($sender, $cert, $chain, $errors) >> return $true >> } >> } catch { >> # 方法2:使用全局回调(旧版.NET Framework) >> $oldCallback = [System.Net.ServicePointManager]::ServerCertificateValidationCallback >> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { >> param($sender, $certificate, $chain, $sslPolicyErrors) >> return $true >> } >> $globalCallbackSet = $true >> } >> } >> >> if ($UseGzipCompression) { >> $handler.AutomaticDecompression = [System.Net.DecompressionMethods]::GZip >> } >> >> # 创建 HttpClient >> $client = New-Object System.Net.Http.HttpClient($handler) >> $client.Timeout = [System.TimeSpan]::FromSeconds($Timeout) >> >> # 创建HttpMethod对象 >> $httpMethod = [System.Net.Http.HttpMethod]::new($Method) >> >> # 创建请求消息 >> $request = New-Object System.Net.Http.HttpRequestMessage($httpMethod, $Uri) >> >> # 添加默认 User-Agent >> if (-not $Headers.ContainsKey('User-Agent')) { >> $request.Headers.TryAddWithoutValidation("User-Agent", "PowerShell-HTTPClient/1.0") >> } >> >> # 添加自定义头 >> foreach ($key in $Headers.Keys) { >> if (-not $request.Headers.TryAddWithoutValidation($key, $Headers[$key])) { >> if (-not $request.Content) { >> $request.Content = New-Object System.Net.Http.StringContent("") >> } >> $request.Content.Headers.TryAddWithoutValidation($key, $Headers[$key]) >> } >> } >> >> # 处理请求体 >> if ($Body -and @('POST','PUT','PATCH') -contains $Method) { >> if ($Body -is [byte[]]) { >> $request.Content = New-Object System.Net.Http.ByteArrayContent($Body) >> } >> elseif ($Body -is [hashtable] -or $Body -is [System.Collections.IDictionary]) { >> $jsonBody = $Body | ConvertTo-Json -Depth 5 -Compress >> $request.Content = New-Object System.Net.Http.StringContent( >> $jsonBody, >> [System.Text.Encoding]::UTF8, >> "application/json" >> ) >> } >> elseif ($Body -is [string]) { >> $request.Content = New-Object System.Net.Http.StringContent( >> $Body, >> [System.Text.Encoding]::UTF8 >> ) >> } >> else { >> throw "Unsupported body type: $($Body.GetType().Name)" >> } >> } >> >> # 发送请求 >> $response = $client.SendAsync($request).GetAwaiter().GetResult() >> >> # 解析响应 >> $result.StatusCode = [int]$response.StatusCode >> $result.StatusMessage = $response.ReasonPhrase >> $result.IsSuccess = $response.IsSuccessStatusCode >> >> $result.Headers = [ordered]@{} >> foreach ($header in $response.Headers) { >> $result.Headers[$header.Key] = $header.Value -join ", " >> } >> >> foreach ($header in $response.Content.Headers) { >> $result.Headers[$header.Key] = $header.Value -join ", " >> } >> >> $result.Content = $response.Content.ReadAsStringAsync().GetAwaiter().GetResult() >> return $result >> } >> catch [System.Threading.Tasks.TaskCanceledException] { >> $result.ErrorMessage = "Request timed out after $Timeout seconds" >> $result.StatusCode = 408 >> $result.StatusMessage = "Timeout" >> return $result >> } >> catch [System.Net.Http.HttpRequestException] { >> # 处理特定HTTP请求异常 >> $ex = $_.Exception >> $result.ErrorMessage = $ex.ToString() >> >> # 检查内部异常类型 >> $currentException = $ex >> $dnsError = $false >> $sslError = $false >> $webException = $false >> >> while ($currentException -ne $null) { >> # 检查DNS错误 >> if ($currentException -is [System.Net.Sockets.SocketException]) { >> $dnsError = $true >> break >> } >> >> # 检查SSL错误 >> if ($currentException -is [System.Security.Authentication.AuthenticationException]) { >> $sslError = $true >> break >> } >> >> # 检查WebException(旧版.NET Framework) >> if ($currentException -is [System.Net.WebException]) { >> $webException = $true >> >> # 检查具体错误类型 >> if ($currentException.Status -eq [System.Net.WebExceptionStatus]::NameResolutionFailure) { >> $dnsError = $true >> } >> elseif ($currentException.Status -eq [System.Net.WebExceptionStatus]::TrustFailure) { >> $sslError = $true >> } >> break >> } >> >> $currentException = $currentException.InnerException >> } >> >> if ($dnsError) { >> $result.StatusCode = 0 >> $result.StatusMessage = "DNSResolutionFailed" >> } >> elseif ($sslError) { >> $result.StatusCode = 495 # 自定义状态码:SSL证书错误 >> $result.StatusMessage = "SSLCertificateError" >> } >> elseif ($webException) { >> $result.StatusCode = 500 >> $result.StatusMessage = "WebException" >> } >> else { >> $result.StatusCode = 500 >> $result.StatusMessage = "HttpRequestError" >> } >> >> return $result >> } >> catch { >> # 通用错误处理 >> $result.ErrorMessage = $_.Exception.ToString() >> $result.StatusCode = 500 >> $result.StatusMessage = "InternalError" >> return $result >> } >> finally { >> $timer.Stop() >> $result.ElapsedMs = $timer.ElapsedMilliseconds >> >> # 恢复全局证书验证回调 >> if ($globalCallbackSet) { >> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $oldCallback >> } >> >> # 安全清理资源 >> if ($response -is [System.IDisposable]) { $response.Dispose() } >> if ($request -is [System.IDisposable]) { $request.Dispose() } >> if ($client -is [System.IDisposable]) { $client.Dispose() } >> if ($handler -is [System.IDisposable]) { $handler.Dispose() } >> } >> } >> PS C:\Users\Administrator> # 创建模块目录 PS C:\Users\Administrator> $moduleDir = "$env:ProgramFiles\WindowsPowerShell\Modules\PSHttpClient" PS C:\Users\Administrator> New-Item -Path $moduleDir -ItemType Directory -Force | Out-Null PS C:\Users\Administrator> PS C:\Users\Administrator> # 保存模块文件 PS C:\Users\Administrator> $functionCode = @' >> # 上面修复后的完整函数代码 >> '@ >> $functionCode | Out-File "$moduleDir\PSHttpClient.psm1" -Encoding UTF8 -Force >> PS C:\Users\Administrator> # 创建模块清单 PS C:\Users\Administrator> New-ModuleManifest -Path "$moduleDir\PSHttpClient.psd1" ` >> -RootModule "PSHttpClient.psm1" ` >> -Author "PowerShell User" ` >> -ModuleVersion "1.0.0" ` >> -Description "Enhanced HTTP client for PowerShell" >> PS C:\Users\Administrator> # 重新加载模块 PS C:\Users\Administrator> Remove-Module PSHttpClient -ErrorAction SilentlyContinue PS C:\Users\Administrator> Import-Module PSHttpClient -Force PS C:\Users\Administrator> PS C:\Users\Administrator> # 测试所有功能 PS C:\Users\Administrator> $testCases = @( >> @{Name = "正常GET请求"; Url = "https://httpbin.org/get"; Method = "GET"; ExpectedCode = 200} >> @{Name = "JSON POST请求"; Url = "https://httpbin.org/post"; Method = "POST"; Body = @{name="Test"}; ExpectedCode = 200} >> @{Name = "自签名证书"; Url = "https://self-signed.badssl.com/"; Method = "GET"; SkipCertificateCheck = $true; ExpectedCode = 200} >> @{Name = "无效域名"; Url = "https://invalid.domain.abc/"; Method = "GET"; ExpectedCode = 0} >> @{Name = "超时测试"; Url = "https://httpbin.org/delay/10"; Method = "GET"; Timeout = 1; ExpectedCode = 408} >> @{Name = "SSL证书错误"; Url = "https://expired.badssl.com/"; Method = "GET"; ExpectedCode = 495} >> ) >> PS C:\Users\Administrator> $results = foreach ($test in $testCases) { >> $params = @{ >> Uri = $test.Url >> Method = $test.Method >> } >> >> if ($test.Body) { $params['Body'] = $test.Body } >> if ($test.SkipCertificateCheck) { $params['SkipCertificateCheck'] = $true } >> if ($test.Timeout) { $params['Timeout'] = $test.Timeout } >> >> try { >> $result = Invoke-EnhancedCurlRequest @params >> } catch { >> $result = [PSCustomObject]@{ >> StatusCode = 500 >> StatusMessage = "UnhandledError" >> ErrorMessage = $_.Exception.Message >> IsSuccess = $false >> ElapsedMs = 0 >> } >> } >> >> [PSCustomObject]@{ >> TestName = $test.Name >> Status = if ($result.StatusCode -eq $test.ExpectedCode) { "✅ PASS" } else { "❌ FAIL" } >> StatusCode = $result.StatusCode >> Expected = $test.ExpectedCode >> Success = $result.IsSuccess >> Error = if ($result.ErrorMessage) { $result.ErrorMessage.Substring(0, [Math]::Min(50, $result.ErrorMessage.Length)) } else { "None" } >> Time = "$($result.ElapsedMs)ms" >> } >> } >> PS C:\Users\Administrator> # 显示测试结果 PS C:\Users\Administrator> $results | Format-Table -AutoSize TestName Status StatusCode Expected Success Error Time -------- ------ ---------- -------- ------- ----- ---- 正常GET请求 ✅ PASS 200 200 True None 1157ms JSON POST请求 ✅ PASS 200 200 True None 1101ms 自签名证书 ❌ FAIL 500 200 False System.Net.Http.HttpRequestException: 发送请求时出错。 --- 1824ms 无效域名 ✅ PASS 0 0 False System.Net.Http.HttpRequestException: 发送请求时出错。 --- 44ms 超时测试 ✅ PASS 408 408 False Request timed out after 1 seconds 1006ms SSL证书错误 ✅ PASS 495 495 False System.Net.Http.HttpRequestException: 发送请求时出错。 --- 986ms PS C:\Users\Administrator> PS C:\Users\Administrator>
08-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值