HiveBrain v1.2.0
Get Started
← Back to all entries
patternshellMinor

Oneliner to extract External IP from IFCONFIG.CO

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
onelinerextractifconfigexternalfrom

Problem

I wrote a small function in powershell that works fine, however I feel its extremely hacky and I'm sure there must be a smarter way to do this. In the interests of learning, what can I do to improve on this?

function WhatsMyIP
{
return ((Invoke-RestMethod -Uri http://ifconfig.co).split("`n") | where {$_ -match "`"ip`""}).split("")[4]
}


I tried this with Invoke-WebRequest but the returned data is the same, except you need to expand the .content property to get at it, making this slightly more clunky than before.

I'd like to do this natively, I realise I can just invoke CURL or what ever but the point is that I am very likely to be on systems where CURL isn't available when I need this.

Solution

I don't like the idea of using Invoke-RestMethod here. Normally it would return an object, but here it just returns html as a string, which isn't much use to us. I guess that's because the payload is not XML or JSON, so PowerShell can't turn it into an object for us.

Invoke-WebRequest in contrast will parse the HTML for us, and then we can filter out the element we want:

function WhatsMyIP
{
    $x = Invoke-WebRequest -Uri http://ifconfig.co
    $elt = $x.AllElements | ? { $_.tagName -eq 'CODE' -and $_.class -eq 'ip' }
    $elt.innerText
}


The question mark ? means "where". (It's an alias for Where-Object.) So, what we are doing is we get all the HTML elements on the page, and we filter out all of them except the ones that have a tagName of 'CODE' and a class of 'ip'. (There will only be one of them on this particular page.) We are catching this element: 1.2.3.4.

That's "screen scraping" though, which is a bit crappy. I notice on the web site that they provide JSON if you give them the right URL. Now we can use Invoke-RestMethod:

function WhatsMyIP
{
    $x = Invoke-RestMethod -Uri ifconfig.co/all.json
    $x.'X-Real-Ip'
}


Note that there's no need to use return. Any unconsumed objects will be put in the pipeline. If you don't understand the pipeline, you should read up on it, because it is key to understanding PowerShell.

Code Snippets

function WhatsMyIP
{
    $x = Invoke-WebRequest -Uri http://ifconfig.co
    $elt = $x.AllElements | ? { $_.tagName -eq 'CODE' -and $_.class -eq 'ip' }
    $elt.innerText
}
function WhatsMyIP
{
    $x = Invoke-RestMethod -Uri ifconfig.co/all.json
    $x.'X-Real-Ip'
}

Context

StackExchange Code Review Q#110451, answer score: 4

Revisions (0)

No revisions yet.