Home > Software design >  VB.NET WebRequest Retrieves No Content
VB.NET WebRequest Retrieves No Content

Time:11-23

I'm working on a VB.NET project (Outlook VSTO) that I want to grab data from Cisco AMP via its API. The issue I'm facing is that although I can successfully authenticate, and I receive a 200 status code, the content length of the response is always -1, and the content I get is always this no matter what information I request from the API: �

I know this is an issue with my VB.NET code because I am able to retrieve the actual information with Python requests with like 2 lines of code and absolutely no issues. According to Cisco AMP's documentation, there are two ways to access the api: either by https://APIGUID:[email protected]/v1/requestedinformation or by http://example.com/v1/requestedinformation with the credentials specified in the headers encoded in base64 (RFC 1945). I can get the proper information with Python from either of these methods, but neither of them work with VB.NET so far.

Here are the two main solutions I have tried in VB.NET, but keep in mind, I have tried both connection methods within each solution I have tried.

Attempt 1 Using WebClient:

    Public Sub Test()
        Dim url As String = "https://" & apiID & ":" & apiKey & "@" & "api.amp.cisco.com/v1/computers"
        MsgBox(url) 'Just to make sure I have the URL properly formatted

        'These two lines are needed to avoid SSL validation. 
        'The network I am working on this from sits behind a proxy for logging reasons,
        'so the certificate will not match the domain. This is 100% necessary.
        Net.ServicePointManager.ServerCertificateValidationCallback = New Net.Security.RemoteCertificateValidationCallback(Function() True)
        Net.ServicePointManager.SecurityProtocol = Net.SecurityProtocolType.Tls12
        
        'I have tried with the Uri data type as well as the url in String format
        Dim uri As Uri = New Uri(url)
        Dim request As Net.WebClient = New Net.WebClient

        'Headers, I copied them verbatim from Python since Python was able to get
        'the response content
        request.Headers.Add("Accept", "*/*") 'I have also tried application/json here
        request.Headers.Add("User-Agent", "python-requests/2.26.0")
        request.Credentials = New Net.NetworkCredential(apiID, apiKey)
        request.Headers.Add("Authorization", "Basic base64string") 'removed the actual base 64 string for privacy reasons, the actual string is in my code.
        request.Headers.Add("Accept-Encoding", "gzip, deflate")

        'I have tried DownloadData as well as DownloadString
        Dim htmlResponse As String = System.Text.Encoding.UTF8.GetString(request.DownloadData(uri))

        'Just using this mail item to display the response content
        Dim mail As Outlook.MailItem = Me.Application.CreateItem(Outlook.OlItemType.olMailItem)
        mail.HTMLBody = htmlResponse

        mail.Display()
    End Sub

Attempt 2 Using HTTPWebRequest:

    Public Sub Test()
        Dim url As String = "https://" & apiID & ":" & apiKey & "@" & "api.amp.cisco.com/v1/computers"
        MsgBox(url)

        'These two lines are needed to avoid SSL validation. 
        'The network I am working on this from sits behind a proxy for logging reasons,
        'so the certificate will not match the domain. This is 100% necessary.
        Net.ServicePointManager.ServerCertificateValidationCallback = New Net.Security.RemoteCertificateValidationCallback(Function() True)
        Net.ServicePointManager.SecurityProtocol = Net.SecurityProtocolType.Tls12

        'Headers, I copied them verbatim from Python since Python was able to get
        'the response content
        Dim uri As Uri = New Uri(url)
        Dim cookies As Net.CookieContainer = New Net.CookieContainer()
        Dim request As Net.HttpWebRequest = Net.HttpWebRequest.Create(uri)
        request.CookieContainer = cookies
        request.ServicePoint.Expect100Continue = False
        request.Accept = "*/*" 'I have also tried application/json here
        request.UserAgent = "python-requests/2.26.0"
        request.KeepAlive = True
        request.Credentials = New Net.NetworkCredential(apiID, apiKey)
        request.PreAuthenticate = True
        request.Headers.Add("Authorization", "Basic base64string")
        request.Headers.Add("Accept-Encoding", "gzip, deflate")

        Dim response As Net.HttpWebResponse = request.GetResponse()
        Dim reader As StreamReader = New StreamReader(response.GetResponseStream())
        Dim htmlResponse As String = reader.ReadToEnd()

        MsgBox(response.StatusCode)

        'Just using this mail item to display the response content
        Dim mail As Outlook.MailItem = Me.Application.CreateItem(Outlook.OlItemType.olMailItem)
        mail.HTMLBody = htmlResponse

        mail.Display()
    End Sub

I've been bashing my head against this for the past few hours, I'm out of ideas at this point. Am I doing something stupid or is there some limitation of VB.NET I'm not aware of?

CodePudding user response:

As it turns out, the solution was quite simple. Either of the above will work, I just needed to remove the Accept-Encoding header.

Note that I added it in the first place because:

  1. Cisco AMP's API states that the Accept-Encoding: gzip header is needed
  2. Python used that exact header and was able to retrieve the data

Really not sure why this is the case, but at any rate, it works now.

  • Related