microsoft-visualbasic-runtime/Extensions/WebServices/WebServiceUtils.vb

777 lines
28 KiB
VB.net
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#Region "Microsoft.VisualBasic::4d5d5bef8e9a9b6e863af14d8d486dff, Microsoft.VisualBasic.Core\Extensions\WebServices\WebServiceUtils.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
' /********************************************************************************/
' Summaries:
' Module WebServiceUtils
'
' Properties: DefaultUA, Protocols, Proxy
'
' Constructor: (+1 Overloads) Sub New
'
' Function: __getMyIPAddress, BuildArgs, (+2 Overloads) BuildReqparm, BuildUrlData, CheckValidationResult
' (+2 Overloads) DownloadFile, GenerateDictionary, GetDownload, GetMyIPAddress, GetProxy
' (+2 Overloads) GetRequest, GetRequestRaw, IsSocketPortOccupied, isURL, IsURLPattern
' (+2 Overloads) POST, POSTFile, (+2 Overloads) PostRequest, PostUrlDataParser, QueryStringParameters
' UrlDecode, UrlEncode, UrlPathEncode
'
' Sub: (+2 Overloads) SetProxy, UrlDecode, UrlEncode
'
' /********************************************************************************/
#End Region
Imports System.Collections.Specialized
Imports System.IO
Imports System.Net
Imports System.Net.Security
Imports System.Runtime.CompilerServices
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Web
Imports Microsoft.VisualBasic.CommandLine.Reflection
Imports Microsoft.VisualBasic.Language
Imports Microsoft.VisualBasic.Language.Default
Imports Microsoft.VisualBasic.Linq.Extensions
Imports Microsoft.VisualBasic.Net
Imports Microsoft.VisualBasic.Net.Http
Imports Microsoft.VisualBasic.Net.Tcp
Imports Microsoft.VisualBasic.Scripting.MetaData
Imports Microsoft.VisualBasic.Text
''' <summary>
''' The extension module for web services works.
''' </summary>
'''
<Package("Utils.WebServices",
Description:="The extension module for web services programming in your scripting.",
Category:=APICategories.UtilityTools,
Publisher:="<a href=""mailto://xie.guigang@gmail.com"">xie.guigang@gmail.com</a>")>
Public Module WebServiceUtils
''' <summary>
''' Web protocols enumeration
''' </summary>
''' <returns></returns>
Public ReadOnly Property Protocols As String() = {"http://", "https://", "ftp://", "sftp://"}
Public Const URLPattern$ = "http(s)?://([\w+?\.\w+])+([a-zA-Z0-9\~\!\@\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\.\:\;\'\,]*)?"
''' <summary>
''' Determine that is this uri string is a network location?
''' (判断这个uri字符串是否是一个网络位置)
''' </summary>
''' <param name="url"></param>
''' <returns></returns>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<Extension> Public Function isURL(url As String) As Boolean
Return url.IndexOfAny({ASCII.LF, ASCII.CR}) = -1 AndAlso url.InStrAny(Protocols) = 1
End Function
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<Extension> Public Function IsURLPattern(str As String) As Boolean
Return str.isURL OrElse str.IsPattern(URLPattern)
End Function
''' <summary>
''' Build the request parameters for the HTTP POST
''' </summary>
''' <param name="dict"></param>
''' <returns></returns>
<ExportAPI("Build.Reqparm",
Info:="Build the request parameters for the HTTP POST")>
<Extension> Public Function BuildReqparm(dict As Dictionary(Of String, String)) As NameValueCollection
Dim reqparm As New NameValueCollection
For Each Value As KeyValuePair(Of String, String) In dict
Call reqparm.Add(Value.Key, Value.Value)
Next
Return reqparm
End Function
''' <summary>
''' Build the request parameters for the HTTP POST
''' </summary>
''' <param name="data"></param>
''' <returns></returns>
<ExportAPI("Build.Reqparm", Info:="Build the request parameters for the HTTP POST")>
<Extension>
Public Function BuildReqparm(data As IEnumerable(Of KeyValuePair(Of String, String))) As Specialized.NameValueCollection
Dim reqparm As New Specialized.NameValueCollection
For Each Value As KeyValuePair(Of String, String) In data
Call reqparm.Add(Value.Key, Value.Value)
Next
Return reqparm
End Function
Const PortOccupied As String = "Only one usage of each socket address (protocol/network address/port) Is normally permitted"
''' <summary>
''' Only one usage of each socket address (protocol/network address/port) Is normally permitted
''' </summary>
''' <param name="ex"></param>
''' <returns></returns>
<Extension> Public Function IsSocketPortOccupied(ex As Exception) As Boolean
If TypeOf ex Is System.Net.Sockets.SocketException AndAlso
InStr(ex.ToString, PortOccupied, CompareMethod.Text) Then
Return True
Else
Return False
End If
End Function
''' <summary>
''' Create a parameter dictionary from the request parameter tokens.
''' (请注意字典的key默认为转换为小写的形式)
''' </summary>
''' <param name="tokens">
''' 元素的个数必须要大于1因为从url里面解析出来的元素之中第一个元素是url本身则不再对url做字典解析
''' </param>
''' <returns>
''' ###### 2016-11-21
''' 因为post可能会传递数组数据进来则这个时候就会出现重复的键名则已经不再适合字典类型了这里改为返回<see cref="NameValueCollection"/>
''' </returns>
<ExportAPI("CreateDirectory", Info:="Create a parameter dictionary from the request parameter tokens.")>
<Extension>
Public Function GenerateDictionary(tokens As String(), Optional lowercase As Boolean = True) As NameValueCollection
Dim out As New NameValueCollection
If tokens.IsNullOrEmpty Then
Return out
End If
If tokens.Length = 1 Then ' 只有url没有附带的参数则返回一个空的字典集合
If InStr(tokens(Scan0), "=") = 0 Then
Return out
End If
End If
Dim LQuery = (From s As String
In tokens
Let p As Integer = InStr(s, "="c)
Let Key As String = Mid(s, 1, p - 1)
Let value = Mid(s, p + 1)
Select Key,
value).ToArray
For Each x In LQuery
Dim name As String = If(lowercase,
x.Key.ToLower,
x.Key)
Call out.Add(name, x.value)
Next
Return out
End Function
''' <summary>
''' 不像<see cref="PostUrlDataParser(String, Boolean)"/>函数这个函数不会替换掉转义字符并且所有的Key都已经被默认转换为小写形式的了
''' </summary>
''' <param name="url">URL parameters</param>
''' <returns></returns>
<ExportAPI("Request.Parser")>
<Extension> Public Function QueryStringParameters(url$, Optional transLower As Boolean = True) As NameValueCollection
Dim tokens$()
With InStr(url, "://")
If .ByRef < 10 AndAlso .ByRef > 0 Then
url = url.GetTagValue("?").Value
End If
tokens = url.Split("&"c)
End With
Return GenerateDictionary(tokens, transLower)
End Function
ReadOnly urlEscaping As [Default](Of Func(Of String, String)) = New Func(Of String, String)(AddressOf UrlEncode)
Friend ReadOnly noEscaping As [Default](Of Func(Of String, String)) = New Func(Of String, String)(Function(s) s)
''' <summary>
''' 生成URL请求的参数
''' </summary>
''' <param name="data"></param>
''' <param name="escaping">是否进行对value部分的字符串数据进行转义</param>
''' <returns></returns>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<Extension> Public Function BuildUrlData(data As IEnumerable(Of KeyValuePair(Of String, String)), Optional escaping As Boolean = False) As String
Return data.Select(Function(x) $"{x.Key}={(noEscaping Or urlEscaping.When(escaping))(x.Value) }").JoinBy("&")
End Function
<ExportAPI("Build.Args")>
Public Function BuildArgs(ParamArray params As String()()) As String
If params.IsNullOrEmpty Then
Return ""
Else
Dim values = params.Select(Function(arg) $"{arg(Scan0)}={arg(1)}").ToArray
Return String.Join("&", values)
End If
End Function
''' <summary>
''' 在服务器端对URL进行解码还原
''' </summary>
''' <param name="s"></param>
''' <param name="encoding"></param>
''' <returns></returns>
<Extension> <ExportAPI("URL.Decode")>
Public Function UrlDecode(s$, Optional encoding As Encoding = Nothing) As String
If s.StringEmpty Then
Return ""
End If
If encoding IsNot Nothing Then
Return HttpUtility.UrlDecode(s, encoding)
Else
Return HttpUtility.UrlDecode(s)
End If
End Function
<ExportAPI("URL.Decode")>
Public Sub UrlDecode(s As String, ByRef output As TextWriter)
If s IsNot Nothing Then
output.Write(UrlDecode(s))
End If
End Sub
''' <summary>
''' 进行url编码将特殊字符进行转码
''' </summary>
''' <param name="s"></param>
''' <param name="encoding"></param>
''' <param name="jswhitespace">
''' 空格符号默认被转义为``+``, 如果这个参数为真的话,则空格会被转义为``%20``
''' </param>
''' <returns></returns>
''' <remarks>
''' A extension method wrapper for <see cref="HttpUtility.UrlEncode"/>
''' </remarks>
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<ExportAPI("URL.Encode")>
<Extension>
Public Function UrlEncode(s As String, Optional encoding As Encoding = Nothing, Optional jswhitespace As Boolean = False) As String
Dim component As String
If encoding IsNot Nothing Then
component = HttpUtility.UrlEncode(s, encoding)
Else
component = HttpUtility.UrlEncode(s)
End If
If jswhitespace Then
' 20190517 因为+号被转义为%2b,所以在这里可以直接替换
' 由空格转义而得到的+符号为%20
component = component.Replace("+", "%20")
End If
Return component
End Function
<ExportAPI("URL.Encode")>
Public Sub UrlEncode(s As String, ByRef output As TextWriter)
If s IsNot Nothing Then
output.Write(UrlEncode(s))
End If
End Sub
''' <summary>
''' 编码整个URL这个函数会自动截取出query string parameter部分然后对截取出来的query string parameter进行编码
''' </summary>
''' <param name="s"></param>
''' <returns></returns>
<ExportAPI("URL.PathEncode")>
<Extension>
Public Function UrlPathEncode(s As String) As String
If s Is Nothing Then
Return Nothing
End If
Dim idx As Integer = s.IndexOf("?"c)
Dim s2 As String = Nothing
If idx <> -1 Then
s2 = s.Substring(0, idx)
s2 = HttpUtility.UrlEncode(s2) & s.Substring(idx)
Else
s2 = HttpUtility.UrlEncode(s)
End If
Return s2
End Function
''' <summary>
''' 假若你的数据之中包含有SHA256的加密数据则非常不推荐使用这个函数进行解析。因为请注意这个函数会替换掉一些转义字符的所以会造成一些非常隐蔽的BUG
''' </summary>
''' <param name="data">转义的时候大小写无关</param>
''' <returns></returns>
'''
<ExportAPI("PostRequest.Parsing")>
<Extension> Public Function PostUrlDataParser(data$, Optional toLower As Boolean = True) As NameValueCollection
If String.IsNullOrEmpty(data) Then
Return New NameValueCollection
End If
Dim params$() = data.UrlDecode.Split("&"c)
Dim table = GenerateDictionary(params, toLower)
Return table
End Function
<ExportAPI("GET", Info:="GET http request")>
<Extension> Public Function GetRequest(strUrl$, ParamArray args As String()()) As String
If args.IsNullOrEmpty Then
Return GetRequest(strUrl)
Else
Dim params As String = BuildArgs(args)
If String.IsNullOrEmpty(params) Then
Return GetRequest(strUrl)
Else
Return GetRequest($"{strUrl}?{params}")
End If
End If
End Function
''' <summary>
''' GET http request
''' </summary>
''' <param name="url"></param>
''' <returns></returns>
<ExportAPI("GET", Info:="GET http request")>
<Extension> Public Function GetRequest(url$, Optional https As Boolean = False, Optional userAgent As String = Nothing) As String
Dim strData As String = ""
Dim strValue As New List(Of String)
Dim reader As New StreamReader(GetRequestRaw(url, https, userAgent), Encoding.UTF8)
Do While True
strData = reader.ReadLine()
If strData Is Nothing Then
Exit Do
Else
strValue += strData
End If
Loop
strData = String.Join(vbCrLf, strValue.ToArray)
Return strData
End Function
Sub New()
ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf CheckValidationResult)
End Sub
Private Function CheckValidationResult(sender As Object,
certificate As X509Certificate,
chain As X509Chain,
errors As SslPolicyErrors) As Boolean
Return True
End Function
''' <summary>
''' Example for xx-net tool:
'''
''' ```
''' http://127.0.0.1:8087/
''' ```
''' </summary>
''' <returns></returns>
Public Property Proxy As String
''' <summary>
'''
''' </summary>
''' <param name="url"></param>
''' <param name="https"></param>
''' <param name="userAgent">
'''
''' fix a bug for github API:
'''
''' Protocol violation using Github api
'''
''' You need to set UserAgent like this:
''' webRequest.UserAgent = "YourAppName"
''' Otherwise it will give The server committed a protocol violation. Section=ResponseStatusLine Error.
''' </param>
''' <returns></returns>
<ExportAPI("GET.Raw", Info:="GET http request")>
<Extension> Public Function GetRequestRaw(url As String,
Optional https As Boolean = False,
Optional userAgent As String = Nothing) As Stream
Dim request As HttpWebRequest
If https Then
request = WebRequest.CreateDefault(New Uri(url))
Else
request = DirectCast(WebRequest.Create(url), HttpWebRequest)
End If
request.Method = "GET"
request.KeepAlive = False
request.ServicePoint.Expect100Continue = False
request.UserAgent = userAgent Or DefaultUA
Dim response As HttpWebResponse = DirectCast(request.GetResponse, HttpWebResponse)
Dim s As Stream = response.GetResponseStream()
Return s
End Function
<ExportAPI("POST", Info:="POST http request")>
Public Function PostRequest(url As String, Optional params As IEnumerable(Of KeyValuePair(Of String, String)) = Nothing) As String
Return url.POST(params.BuildReqparm)
End Function
<ExportAPI("POST", Info:="POST http request")>
Public Function PostRequest(url As String, ParamArray params As String()()) As String
Dim post As KeyValuePair(Of String, String)()
If params Is Nothing Then
post = Nothing
Else
post = params.Select(Function(value) New KeyValuePair(Of String, String)(value(0), value(1))).ToArray
End If
Return PostRequest(url, post)
End Function
''' <summary>
''' POST http request for get html.
''' (请注意,假若<paramref name="params"/>之中含有字符串数组的话,则会出错,这个时候需要使用
''' <see cref="Post(String, Dictionary(Of String, String()), String, String, String)"/>方法)
''' </summary>
''' <param name="url$"></param>
''' <param name="params"></param>
''' <param name="Referer$"></param>
''' <returns></returns>
<ExportAPI("POST", Info:="POST http request")>
<Extension> Public Function POST(url$,
Optional params As NameValueCollection = Nothing,
Optional headers As Dictionary(Of String, String) = Nothing,
Optional Referer$ = "",
Optional proxy$ = Nothing,
Optional contentEncoding As Encodings = Encodings.UTF8) As String
Static emptyBody As New [Default](Of NameValueCollection) With {
.Value = New NameValueCollection,
.assert = Function(c)
Return c Is Nothing OrElse DirectCast(c, NameValueCollection).Count = 0
End Function
}
Using request As New WebClient
Call request.Headers.Add("User-Agent", UserAgent.GoogleChrome)
Call request.Headers.Add(NameOf(Referer), Referer)
For Each header In headers.SafeQuery
If Not request.Headers.ContainsKey(header.Key) Then
request.Headers.Add(header.Key, header.Value)
End If
Next
If String.IsNullOrEmpty(proxy) Then
proxy = WebServiceUtils.Proxy
End If
If Not String.IsNullOrEmpty(proxy) Then
Call request.SetProxy(proxy)
End If
Call $"[POST] {url}....".__DEBUG_ECHO
Dim response As Byte() = request.UploadValues(url, "POST", params Or emptyBody)
Dim str$ = contentEncoding.CodePage.GetString(response)
Call $"[GET] {response.Length} bytes...".__DEBUG_ECHO
Return str
End Using
End Function
''' <summary>
''' 通过post上传文件
''' </summary>
''' <param name="url$"></param>
''' <param name="name$"></param>
''' <param name="referer$"></param>
''' <returns></returns>
<Extension>
Public Function POSTFile(url$, buffer As Byte(), Optional name$ = "", Optional referer$ = Nothing) As String
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
request.Method = "POST"
request.Accept = "application/json"
request.ContentLength = buffer.Length
request.ContentType = "multipart/form-data; boundary=------WebKitFormBoundaryBpijhG6dKsQpCMdN--;"
request.UserAgent = UserAgent.GoogleChrome
request.Referer = referer
' request.Headers("fileName") = name Or File.FileName.AsDefault
If Not String.IsNullOrEmpty(Proxy) Then
Call request.SetProxy(Proxy)
End If
Call $"[POST] {url}....".__DEBUG_ECHO
' post data Is sent as a stream
With request.GetRequestStream()
' Dim buffer = File.ReadBinary
' Call New StreamWriter(.ByRef).Write(vbCrLf)
' Call .Flush()
Call .Write(buffer, Scan0, buffer.Length)
Call .Flush()
End With
' returned values are returned as a stream, then read into a string
Dim response = DirectCast(request.GetResponse(), HttpWebResponse)
Using responseStream As New StreamReader(response.GetResponseStream())
Dim html As New StringBuilder
Dim s As New Value(Of String)
Do While Not (s = responseStream.ReadLine) Is Nothing
Call html.AppendLine(+s)
Loop
Call $"Get {html.Length} bytes from server response...".__DEBUG_ECHO
Return html.ToString
End Using
End Function
''' <summary>
''' POST http request for get html
''' </summary>
''' <param name="url$"></param>
''' <param name="data"></param>
''' <param name="Referer$"></param>
''' <returns></returns>
<ExportAPI("POST", Info:="POST http request")>
<Extension> Public Function POST(url$, data As Dictionary(Of String, String()),
Optional Referer$ = "",
Optional proxy$ = Nothing,
Optional ua As String = UserAgent.GoogleChrome) As String
Dim postString As New List(Of String)
For Each postValue As KeyValuePair(Of String, String()) In data
postString += postValue.Value _
.Select(Function(v) postValue.Key & "=" & HttpUtility.UrlEncode(v))
Next
Dim postData As String = postString.JoinBy("&")
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
request.Method = "POST"
request.Accept = "application/json"
request.ContentLength = postData.Length
request.ContentType = "application/x-www-form-urlencoded; charset=utf-8"
request.UserAgent = ua
request.Referer = Referer
If Not String.IsNullOrEmpty(proxy) Then
Call request.SetProxy(proxy)
End If
Call $"[POST] {url}....".__DEBUG_ECHO
' post data Is sent as a stream
Using sender As New StreamWriter(request.GetRequestStream())
sender.Write(postData)
End Using
' returned values are returned as a stream, then read into a string
Dim response = DirectCast(request.GetResponse(), HttpWebResponse)
Using responseStream As New StreamReader(response.GetResponseStream())
Dim html As New StringBuilder
Dim s As New Value(Of String)
Do While Not (s = responseStream.ReadLine) Is Nothing
Call html.AppendLine(+s)
Loop
Call $"[GET] {html.Length} bytes...".__DEBUG_ECHO
Return html.ToString
End Using
End Function
<Extension>
Public Sub SetProxy(ByRef request As HttpWebRequest, proxy As String)
request.Proxy = proxy.GetProxy
End Sub
<Extension>
Public Sub SetProxy(ByRef request As WebClient, proxy As String)
request.Proxy = proxy.GetProxy
End Sub
<Extension>
Public Function GetProxy(proxy As String) As WebProxy
Return New WebProxy With {
.Address = New Uri(proxy),
.Credentials = New NetworkCredential()
}
End Function
''' <summary>
''' 设置默认的http请求的user-agent默认为Google Chrome的UA字符串
''' </summary>
''' <returns></returns>
Public Property DefaultUA As [Default](Of String) = UserAgent.GoogleChrome
#If FRAMEWORD_CORE Then
''' <summary>
''' download the file from <paramref name="strUrl"></paramref> to <paramref name="save">local file</paramref>.
''' </summary>
''' <param name="strUrl"></param>
''' <param name="save">The file path of the file saved</param>
''' <returns></returns>
''' <remarks></remarks>
<ExportAPI("wget", Info:="Download data from the specific URL location.")>
<Extension> Public Function DownloadFile(<Parameter("url")> strUrl$,
<Parameter("Path.Save", "The saved location of the downloaded file data.")>
save$,
Optional proxy$ = Nothing,
Optional ua$ = Nothing,
Optional retry% = 0,
Optional progressHandle As DownloadProgressChangedEventHandler = Nothing,
Optional refer$ = Nothing,
<CallerMemberName>
Optional trace$ = Nothing) As Boolean
#Else
''' <summary>
''' download the file from <paramref name="strUrl"></paramref> to <paramref name="SavedPath">local file</paramref>.
''' </summary>
''' <param name="strUrl"></param>
''' <param name="SavedPath"></param>
''' <returns></returns>
''' <remarks></remarks>
<Extension> Public Function DownloadFile(strUrl As String, SavedPath As String) As Boolean
#End If
RE0:
Try
Using browser As New WebClient()
If Not String.IsNullOrEmpty(proxy) Then
Call browser.SetProxy(proxy)
End If
If Not refer.StringEmpty Then
browser.Headers.Add(NameOf(refer), refer)
End If
If Not progressHandle Is Nothing Then
AddHandler browser.DownloadProgressChanged, progressHandle
End If
Call browser.Headers.Add(UserAgent.UAheader, ua Or DefaultUA)
Call $"{strUrl} --> {save}".__DEBUG_ECHO
Call save.ParentPath.MkDIR
Call browser.DownloadFile(strUrl, save)
End Using
Return True
Catch ex As Exception
Call App.LogException(New Exception(strUrl, ex), trace)
Call ex.PrintException
If retry > 0 Then
retry -= 1
GoTo RE0
Else
End If
Return False
Finally
If save.FileExists Then
Call $"[{FileIO.FileSystem.GetFileInfo(save).Length} Bytes]".__DEBUG_ECHO
Else
Call $"Download failure!".__DEBUG_ECHO
End If
End Try
End Function
''' <summary>
''' 使用GET方法下载文件
''' </summary>
''' <param name="url"></param>
''' <param name="savePath"></param>
''' <returns></returns>
'''
<ExportAPI("GET.Download", Info:="Download file from http request and save to a specific location.")>
<Extension> Public Function GetDownload(url As String, savePath As String) As Boolean
Try
Dim responseStream As Stream = GetRequestRaw(url)
Dim localBuffer As Stream = responseStream.CopyStream
Call $"[{localBuffer.Length} Bytes]".__DEBUG_ECHO
Return localBuffer.FlushStream(savePath)
Catch ex As Exception
ex = New Exception(url, ex)
Call ex.PrintException
Call App.LogException(ex)
Return False
End Try
End Function
Public Const IPAddress As String = "http://ipaddress.com/"
''' <summary>
''' Microsoft DNS Server
''' </summary>
Public Const MicrosoftDNS As String = "4.2.2.1"
''' <summary>
''' 获取我的公网IP地址假若没有连接互联网的话则会返回局域网IP地址
''' </summary>
''' <returns></returns>
Public Function GetMyIPAddress() As String
Dim hasInternet As Boolean
Try
hasInternet = Not PingUtility.Ping(System.Net.IPAddress.Parse(MicrosoftDNS)) > Integer.MaxValue
Catch ex As Exception
hasInternet = False
End Try
If hasInternet Then
' IPAddress on Internet
Return __getMyIPAddress()
Else
' IPAddress in LAN
Return TcpRequest.LocalIPAddress
End If
End Function
Public Const RegexIPAddress As String = "\d{1,3}(\.\d{1,3}){3}"
Private Function __getMyIPAddress() As String
Dim page As String = IPAddress.GET
Dim ipResult As String = Regex.Match(page, $"IP[:] {RegexIPAddress}<br><img", RegexOptions.IgnoreCase).Value
ipResult = Regex.Match(ipResult, RegexIPAddress).Value
Return ipResult
End Function
End Module