如何从PowerShell请求的404页面获得响应

时间:2014-07-31 11:25:07

标签: powershell teamcity

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

当从浏览器(或提琴手)调用时,我得到以下内容:

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,那么我就不会更聪明了。

4 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:3)

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.htm 404 找不到

另一种方法:

$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包含你正在寻找的错误消息。 (来源:Error Handling in System.Net.HttpWebRequest::GetResponse()

答案 2 :(得分:0)

另一个简单的示例,希望对您有所帮助:

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          

答案 3 :(得分:-3)

您可以尝试使用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)

然后验证您的网址以确保它不是错误页面

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()。

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