如何从powershell请求的404页面中获得响应?



我必须调用TeamCity公开的API,它将告诉我用户是否存在。API的url是:http://myteamcityserver.com:8080/httpAuth/app/rest/users/monkey

当从浏览器(或fiddler)调用

时,我得到以下返回:

Error has occurred during request processing (Not Found).
Error: jetbrains.buildServer.server.rest.errors.NotFoundException: No user can be found by username 'monkey'.
Could not find the entity requested. Check the reference is correct and the user has permissions to access the entity.

我必须使用powershell调用API。当我这样做时,我得到一个异常,我看不到上面的文本。这是我使用的powershell:

try{
    $client = New-Object System.Net.WebClient
    $client.Credentials = New-Object System.Net.NetworkCredential $TeamCityAgentUserName, $TeamCityAgentPassword
    $teamCityUser = $client.DownloadString($url)
    return $teamCityUser
}
catch
{
    $exceptionDetails = $_.Exception
    Write-Host "$exceptionDetails" -foregroundcolor "red"
}

例外:

System.Management.Automation.MethodInvocationException: Exception calling "DownloadString" with "1" argument(s): "The remote server returned an error: (404) Not Found." ---> System.Net.WebException: The remote server returned an error: (404) Not Found.
   at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
   at System.Net.WebClient.DownloadString(Uri address)
   at CallSite.Target(Closure , CallSite , Object , Object )
   --- End of inner exception stack trace ---
   at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
   at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)

我需要能够检查返回的页面是否包含上述文本。这样我就知道是否应该自动创建一个新用户。我可以只检查404,但我担心的是,如果API被更改,调用真的返回404,那么我将不知道。

更改catch子句以捕获更具体的WebException,然后您可以在其上使用Response属性以获得状态代码:

{
  #...
} 
catch [System.Net.WebException] 
{
    $statusCode = [int]$_.Exception.Response.StatusCode
    $html = $_.Exception.Response.StatusDescription
}

BrokenGlass给出了答案,但这可能有所帮助:

try
{
  $URI='http://8bit-museum.de/notfound.htm'
  $HTTP_Request = [System.Net.WebRequest]::Create($URI)
  "check: $URI"
  $HTTP_Response = $HTTP_Request.GetResponse()
  # We then get the HTTP code as an integer.
  $HTTP_Status = [int]$HTTP_Response.StatusCode
} 
catch [System.Net.WebException] 
{
    $statusCode = [int]$_.Exception.Response.StatusCode
    $statusCode
    $html = $_.Exception.Response.StatusDescription
    $html
}
$HTTP_Response.Close()

反应:检查:http://8bit-museum.de/notfound.htm404没有找到

另一种方法:

$URI='http://8bit-museum.de/notfound.htm'
try {
  $HttpWebResponse = $null;
  $HttpWebRequest = [System.Net.HttpWebRequest]::Create("$URI");
  $HttpWebResponse = $HttpWebRequest.GetResponse();
  if ($HttpWebResponse) {
    Write-Host -Object $HttpWebResponse.StatusCode.value__;
    Write-Host -Object $HttpWebResponse.GetResponseHeader("X-Detailed-Error");
  }
}
catch {
  $ErrorMessage = $Error[0].Exception.ErrorRecord.Exception.Message;
  $Matched = ($ErrorMessage -match '[0-9]{3}')
  if ($Matched) {
    Write-Host -Object ('HTTP status code was {0} ({1})' -f $HttpStatusCode, $matches.0);
  }
  else {
    Write-Host -Object $ErrorMessage;
  }
  $HttpWebResponse = $Error[0].Exception.InnerException.Response;
  $HttpWebResponse.GetResponseHeader("X-Detailed-Error");
}

如果我理解这个问题,那么$ErrorMessage = $Error[0]. exception . errorrecord . exception。Message包含您正在查找的错误消息。(来源:System.Net.HttpWebRequest::GetResponse()中的错误处理)

又一个简单的例子,希望对大家有所帮助:

BEGIN
{
    # set an object to store results
    $queries = New-Object System.Collections.ArrayList
    Function Test-Website($Site)
    {
        try
        {
            # check the Site param passed in
            $request = Invoke-WebRequest -Uri $Site
        }
        catch [System.Net.WebException] # web exception
        {
            # if a 404
            if([int]$_.Exception.Response.StatusCode -eq 404)
            {
                $request = [PSCustomObject]@{Site=$site;ReturnCode=[int]$_.Exception.Response.StatusCode}
            }
            else
            {
                # set a variable to set a value available to automate with later
                $request = [PSCustomObject]@{Site=$site;ReturnCode='another_thing'}
            }
        }
        catch
        {
            # available to automate with later
            $request = [PSCustomObject]@{Site=$site;ReturnCode='request_failure'}
        }
        # if successful as an invocation and has
        # a StatusCode property
        if($request.StatusCode)
        {
            $siteURI = $Site
            $response = $request.StatusCode
        }
        else
        {
            $response = $request.ReturnCode
        }
        # return the data   
        return [PSCustomObject]@{Site=$Site;Response=$response}
    }
}
PROCESS
{
    # test all the things
    $nullTest = Test-Website -Site 'http://www.Idontexist.meh'
    $nonNullTest = Test-Website -Site 'https://www.stackoverflow.com'
    $404Test = Test-Website -Site 'https://www.stackoverflow.com/thispagedoesnotexist'
    # add all the things to results
    $queries.Add($nullTest) | Out-Null
    $queries.Add($nonNullTest) | Out-Null
    $queries.Add($404Test) | Out-Null
    # show the info
    $queries | Format-Table
}
END{}
输出:

Site                                               Response     
----                                               --------     
http://www.Idontexist.meh                          another_thing
https://www.stackoverflow.com                      200          
https://www.stackoverflow.com/thispagedoesnotexist 404          

您可以尝试使用Internet Explorer COM对象代替。它允许您检查浏览器返回代码并导航HTML对象模型。

注意:我发现你需要在一个提升的PowerShell提示符下运行这个命令,以维护COM对象的定义。

$url = "http://myteamcityserver.com:8080/httpAuth/app/rest/users/monkey"
$ie = New-Object -ComObject InternetExplorer.Application

添加到查看浏览器

$ie.visibility = $true

导航到站点

$ie.navigate($url)

这将暂停脚本直到页面完全加载

do { start-sleep -Milliseconds 250 } until ($ie.ReadyState -eq 4)

然后验证你的URL以确保它不是一个错误页面

if ($ie.document.url -ne $url) { 
   Write-Host "Site Failed to Load" -ForegroundColor "RED"
} else {
   [Retrieve and Return Data]
}

你可以通过$ie.document导航HTML对象模型。使用Get-Member和HTML方法,如GetElementsByTagName()或GetElementById()。

如果凭据是一个问题,将其构建到一个函数中,然后使用Invoke-Command和-Credentials参数来定义您的登录信息。

最新更新