Jump to content

proxy authentication in http request


Recommended Posts

"HttpSetProxy" is capable to make proxy authenticated by setting a user name and the password.

However,when sending http request using winhttp's functions, how to make the proxy authenticated?

This is the code I use.

#include-once
#include "winhttp.au3"
Global Const $tagWINHTTP_PROXY_INFO = "DWORD  dwAccessType;ptr lpszProxy;ptr lpszProxyBypass;"

;~  #FUNCTION# ;===============================================================================

;~  函数名...........: _WinHTTP_GetRespond
;~  描述.............: 完整的HTTP传输过程
;~  函数用法.........: _WinHTTP_GetRespond($hRequest, $ConnectURL [, Mode[,$hTimeOut[,$Context[,$Cookies[,$MoreHeader[,$ProxyServer[, $FuncName[, $ParamArray]]]]]]]])
;~
;~  参数解释.........: $hRequest - 由 _WinHttpOpen() 函数返回的句柄 或 字符串 (Agent 的描述,也可使用-1,Dafult来创建默认描述)
;~                  $ConnectURL - 请求的URL地址,其形式可为 http://UserName:UserPassWord@127.0.0.1:8181/winhttp_getrespondUpdate/
;~                  $Mode - 本函数定义的模式:
;~                              0    GET (默认)
;~                              1    POST
;~                              2    返回服务器返回的内容(禁用检测的话,+256)
;~                              4    返回完整的Header
;~                              8    禁用重定向
;~                              16   禁用SSL的证书检测
;~                              32   使用自定义函数后立即返回
;~                              64   返回Connection句柄(即不关闭Connection句柄)
;~                              128  访问地址为'[0x00000]' + 'http://' 的形式(即使用Connection句柄作为当期连接)
;~                              256  返回内容绝对为二进制
;~                  $hTimeOut       - 超时MS(正整数,或一维四元数组)
;~                  $Context        - 请求需要发送的内容,一般用于POST中        (字符串)
;~                  $Cookies        - 指定文件头 Cookies (字符串)
;~                  $MoreHeader     - 指定更多的文件头信息 (单一字符串,字符串内可包含回车符)
;~                  $ProxyServer    - 代理服务器地址 xx.xx.xx.xx:xx (字符串)
;~                  $FuncName       - 用户自定义过程名称 (执行时机为确定请求有效后,优先于本过程的文件头及数据获取过程)
;~                  $ParamArray     - 用户自定义过程所需参数构成的数组
;~
;~   函数返回值......: 如果成功的话 - 返回一维8元的数组
;~                            0        -        数据内容                ( 二进制的字符串或字符串,要强制使用二进制模式,请使用256模式,并根据需要使用 Binary() 或 BinarytoString() 函数 )
;~                            1        -        服务器状态
;~                            2        -        文件长度
;~                            3        -        Cookies
;~                            4        -        重定向       (该重定向为完整的URL地址)
;~                            5        -        编码类型
;~                            6        -        完整Header
;~                            7        -        Connection 句柄
;~                         (无内容时,上述任何一个元素均可能为-1)

;~                  如果失败的话 - 设置@error,返回最后的错误代码:
;~                      @Error:
;~                          1        -        打开请求失败
;~                          2        -        打开请求失败或无法设置重定向
;~                          4        -        无法发送请求
;~                          5        -        服务器无回应或超时或使用SSL验证
;~  作者 ............: Republican
;~  注意点 ..........: 如果Header为多行数据,请使用@CRLF为每行非开
;~  相关函数 ........: Winhttp.Au3
;~  链接 ............: http://msdn.microsoft.com/en-us/library/aa384087(VS.85).aspx
;~  有无例子 ........: Yes
;~  日期 ............: 2011.2.19


Func _WinHTTP_GetRespond($hOpen, $ConnectURL, $Mode = Default, $hTimeOut = Default, $Context = Default, $Cookies = Default, $MoreHeader = Default, $ProxyServer= Default, $FuncName = Default, $ParamArray = -1)

    Local $hConnect
    ; ==== 判断基本连接信息 ====
    If $hOpen = "" Or $ConnectURL = "" Then Return SetError(1,0,-1)
    ; ==== 非句柄时,由函数创建句柄 ====
    Local $SimpleMode = 0
    If IsString($hOpen) Then
        $SimpleMode = 1
        $hOpen = _WinHttpOpen($hOpen)
    ElseIf $hOpen = -1 Or $hOpen = Default Then
        $SimpleMode = 1
        $hOpen = _WinHttpOpen()
    EndIf
    ; ==== 分解模式 $Mode 设定  ====
    If $Mode = Default Or $Mode = -1 Then $Mode = 0
    $Mode = _NumberToBinary_Winhttp($Mode)
    If Not IsArray($Mode) Then Return SetError(-1,0,-1)
    ; ==== 提取网址中包含的句柄 ====
    If $Mode[7] = 1 Then
        Local $Distinguish = StringRegExp($ConnectURL,'(.*?)(http.*)',3)
        If IsArray($Distinguish) Then
            $hConnect = $Distinguish[0]
            $ConnectURL = $Distinguish[1]
        EndIf
    EndIf

    ; ==== 拆分网址 ====
    $ConnectURL=_WinHttpCrackUrl($ConnectURL,$ICU_DECODE)
    If @error Or Not IsArray($ConnectURL) Then Return SetError(1,0,_GetLastError_Winhttp())

    ; ==== 重新定义变量,方便阅读 ====
    Local $ServerHost = $ConnectURL[2]
    Local $Port=$ConnectURL[3]
    Local $ObjectFile=$ConnectURL[6]&$ConnectURL[7]
    Local $sFlags = Default
    If $ConnectURL[1] = 2 Then $sFlags = $WINHTTP_FLAG_SECURE   ;=====判断是否使用SSL连接

    ; ==== 代理服务器设定 ====
    If $ProxyServer <> -1 And $ProxyServer <> Default Then

        Local $tProxyInfo
        $tProxyInfo = _WinHttpProxyInfoCreate($WINHTTP_ACCESS_TYPE_NAMED_PROXY, $ProxyServer, "localhost")
        _WinHttpSetOption($hOpen, $WINHTTP_OPTION_PROXY, $tProxyInfo[0])
    EndIf

    ; ==== 使用句柄创建连接(128模式下使用) ====
    Switch $Mode[7]
        Case 0
            $hConnect=_WinHttpConnect($hOpen, $ServerHost,$Port)
    EndSwitch
Local $hRequest
    ; ==== 创建连接 ====
    Switch $Mode[0]
        Case 0
            $hRequest = _WinHttpOpenRequest($hConnect, "GET", $ObjectFile,Default,Default,Default,$sFlags)
            If @error Or $hRequest = 0 Then Return SetError(2,0,_GetLastError_Winhttp())
        Case 1
            $hRequest = _WinHttpOpenRequest($hConnect, "POST", $ObjectFile,Default,Default,Default,$sFlags)
            If @error Or $hRequest = 0  Then Return SetError(2,0,_GetLastError_Winhttp())
        EndSwitch

    ; ==== 关闭SSL中证书的验证 ====
    If $Mode[4] = 1 Then
        _WinHttpSetOption($hRequest,$WINHTTP_OPTION_SECURITY_FLAGS,$SECURITY_FLAG_IGNORE_UNKNOWN_CA)        ;使用非权威机构签发的证书
        _WinHttpSetOption($hRequest,$WINHTTP_OPTION_SECURITY_FLAGS,$SECURITY_FLAG_IGNORE_CERT_CN_INVALID)       ;使用公共名称无效的证书
        _WinHttpSetOption($hRequest,$WINHTTP_OPTION_SECURITY_FLAGS,$SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)     ;使用过期的证书
;~      _WinHttpSetOption($hRequest,$WINHTTP_OPTION_SECURITY_FLAGS,$SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)      ;使用非服务器颁发的证书
    EndIf

    ; ==== 设置超时 ====
    If $hTimeOut <> -2 And $hTimeOut <> Default And $hTimeOut <> "" Then
        If IsArray($hTimeOut) And UBound($hTimeOut) = 4 Then
            MsgBox(0,"",$hTimeOut)
            _WinHttpSetTimeouts($hRequest,$hTimeOut[0],$hTimeOut[1],$hTimeOut[2],$hTimeOut[3])
        ElseIf IsNumber($hTimeOut) Then
            _WinHttpSetTimeouts($hRequest,$hTimeOut,$hTimeOut,$hTimeOut,$hTimeOut)
        EndIf
    EndIf
    ; ==== 登录需要用户验证的HTTP服务器 ====
    If $ConnectURL[4] <> "" Or $ConnectURL[5] <> "" Then _WinHttpSetCredentials($hRequest, $WINHTTP_AUTH_TARGET_SERVER, $WINHTTP_AUTH_SCHEME_BASIC, $ConnectURL[4], $ConnectURL[5])
    ; ==== 禁止重定向 ====
    If $Mode[3] = 1 Then _WinHttpSetOption($hRequest,$WINHTTP_OPTION_DISABLE_FEATURE,$WINHTTP_DISABLE_REDIRECTS)
    If @error Then Return SetError(3,0,_GetLastError_Winhttp())

    ; ==== Header构建 ====
    Local $BinaryMode=0
    If $Context <> -1 And $Context <> Default And $Context <> "" Then
        Switch IsString($Context)
            Case 1
                _WinHttpAddRequestHeaders($hRequest, "Content-Length: "&StringLen($ConText)&@CRLF)
            Case 0
                _WinHttpAddRequestHeaders($hRequest, "Content-Length: "&BinaryLen($ConText)&@CRLF)
                $BinaryMode = 1
        EndSwitch
    EndIf
    If $Cookies <> -1 And $Cookies <> Default And $Cookies <> "" Then _WinHttpAddRequestHeaders($hRequest, "Cookie: "&$Cookies&@CRLF)
    If $MoreHeader <> "" And $MoreHeader <> -1 And $MoreHeader <> Default Then _WinHttpAddRequestHeaders($hRequest,$MoreHeader)

    ; ==== 发送数据 ====
    _WinHttpSendRequest($hRequest)
    If @error Then Return SetError(4,0,_GetLastError_Winhttp())
    ; ==== 发送POST数据 ====
    If $Context <> -1 And $Context <> Default And $Context <> "" Then
        Switch $BinaryMode
            Case 0
                _WinHttpWriteData($hRequest,$Context)
            Case 1
                _WinHttpWriteData($hRequest,$Context,1)
        EndSwitch
    EndIf

    ; ==== 接受服务器回应 ====
    _WinHttpReceiveResponse($hRequest)
    ; ==== 判断数据是否有效 ====
    If Not _WinHttpQueryDataAvailable($hRequest) Then Return SetError(5,0,_GetLastError_Winhttp())

    ; ==== 自定义函数处理过程(此时开始调用外部函数) ====
    If $FuncName <> "" And $FuncName <> -1 And $FuncName <> Default Then
        If $ParamArray <> "" Then
            Local $FuncArray[UBound($ParamArray) +1]
            $FuncArray[0] = "CallArgArray"
            For $i = 1 To UBound($ParamArray)
                $FuncArray[$i] = $ParamArray [$i -1]
                If StringLeft($ParamArray [$i -1],1) = "$" Then $FuncArray[$i] = Eval(StringTrimLeft($FuncArray[$i],1))
            Next
            Call($FuncName,$FuncArray)
        Else
            Call($FuncName)
        EndIf
        If $Mode[5]  = 1 Then
            _WinHttpCloseHandle($hRequest)
            _WinHttpCloseHandle($hConnect)
            If $SimpleMode = 1 Then _WinHttpCloseHandle($hOpen)
            Return 1
        EndIf
    EndIf

    ; ==== 函数返回数据构建 ====
    Local $iReturn[8] = [-1,-1,-1,-1,-1,-1,-1,-1]
    If $Mode[2] = 1 Then $iReturn[6]=_WinHttpQueryHeaders($hRequest)                ;完整的Header信息
    $iReturn[1]=_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_STATUS_CODE)  ;服务器状态
    $iReturn[2]=_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_CONTENT_LENGTH)   ;文件长度
    ; ==== Cookies拆分 ====
    $iReturn[3] =_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_SET_COOKIE,Default,0)        ;Cookies with CRLF换行



    If $iReturn[3] <> "" Then
        For $i = 1 To 20
            Local $TempCookies = _WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_SET_COOKIE,Default,$i)
            If $TempCookies <> "" Then
                $iReturn[3] &= @CRLF & $TempCookies
            Else
                $i = 21
                $TempCookies = 0
            EndIf
        Next
    EndIf
    ; ==== 完整的网址重定向构建 ====
    $iReturn[4]=_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_LOCATION)         ;重定向及其处理过程
    If $iReturn[4] <> "" Then
        Local $RedictURL=_WinHttpCrackUrl($iReturn[4])
        If @error Then
             $RedictURL = $ConnectURL
            $RedictURL[6] = $iReturn[4]
            $RedictURL[7] = ""
            $iReturn[4] = _WinHttpCreateUrl($RedictURL)
        EndIf
        $RedictURL = 0
    EndIf
    $iReturn[5]=_WinHttpQueryHeaders($hRequest,$WINHTTP_QUERY_CONTENT_TYPE)     ;编码类型
    ; ==== 返回-1替代空数据 ====
    For $i = 1 To 5
        If $iReturn[$i] = "" Then $iReturn[$i] = -1
    Next
    ; ==== 读取返回正文数据 ====
    Local $rDate
    If $Mode[1] = 1 Then
        Switch $iReturn[2]
            Case -1,""
                $rDate =Binary("")
                While 1
                    $rDate &= _WinHttpReadData($hRequest,2,1024 * 16)
                    If @error Then ExitLoop
                    Sleep(10)
                WEnd
                $iReturn[0] = Binary($rDate)
            Case Else
                $iReturn[0] = _WinHttpReadData($hRequest,2,$iReturn[2])
        EndSwitch
        ; ==== 转回字符串 ====
        If $Mode[8] = 0 Then
            Local $StringText[4] = ['text/html','text/xml','application/xhtml+xml','text/plain'],$FindText = 0,$StringType[1] = ["UTF-8"],$FindType = -1
            For $i = 0 To UBound($StringText) -1
                If StringInStr($iReturn[5],$StringText[$i]) Then
                    $FindText = 1
                    ExitLoop
                EndIf
            Next
            If $FindText Then
                For $i = 0 To 0
                    If StringInStr($iReturn[5],$StringType[$i]) Then
                        $FindType = $i
                        ExitLoop
                    EndIf
                Next
                Switch $FindType
                    Case 0
                        $iReturn[0] = BinaryToString($iReturn[0],4)
                    Case Else
                        $iReturn[0] = BinaryToString($iReturn[0])
                EndSwitch
            EndIf
        EndIf

    EndIf

    ; ==== 判断是否关闭句柄 ====
    _WinHttpCloseHandle($hRequest)
    Switch $Mode[6]
        Case 1
            $iReturn[7] = $hConnect
        Case Else
            _WinHttpCloseHandle($hConnect)
    EndSwitch
    If $SimpleMode = 1 Then _WinHttpCloseHandle($hOpen)
    Return $iReturn
EndFunc

;-----LastError Meaning:
;~ http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx
;~ http://msdn.microsoft.com/en-us/library/aa385465(v=VS.85).aspx
Func _GetLastError_Winhttp()
    Local $lastError = DllCall ( "kernel32.dll", "dword", "GetLastError" )
    Return $lastError[0]
EndFunc

Func _NumberToBinary_Winhttp($iNumber)
    Local $sBinString = "",$ModeNum = 11, $Numbers[$ModeNum]
    Local $iUnsignedNumber=BitAND($iNumber,0x7FFFFFFF)
    Do
        $sBinString = BitAND($iUnsignedNumber, 1) & $sBinString
        $iUnsignedNumber = BitShift($iUnsignedNumber, 1)
    Until Not $iUnsignedNumber

    $sBinString = StringRight("0000000000000000" &$sBinString,$ModeNum)
    For $i = 0 To $ModeNum -1
        $Numbers[$i] = StringMid($sBinString,$ModeNum - $i,1)
    Next
    Return $Numbers

EndFunc   ;==>_NumberToBinary

Func _WinHttpProxyInfoCreate($dwAccessType, $sProxy, $sProxyBypass)
    Local $tWINHTTP_PROXY_INFO[2] = [DllStructCreate($tagWINHTTP_PROXY_INFO), DllStructCreate('wchar proxychars[' & StringLen($sProxy)+1 & ']; wchar proxybypasschars[' & StringLen($sProxyBypass)+1 & ']')]
    DllStructSetData($tWINHTTP_PROXY_INFO[0], "dwAccessType", $dwAccessType)
    If StringLen($sProxy) Then DllStructSetData($tWINHTTP_PROXY_INFO[0], "lpszProxy", DllStructGetPtr($tWINHTTP_PROXY_INFO[1], 'proxychars'))
    If StringLen($sProxyByPass) Then DllStructSetData($tWINHTTP_PROXY_INFO[0], "lpszProxyBypass", DllStructGetPtr($tWINHTTP_PROXY_INFO[1], 'proxybypasschars'))
    DllStructSetData($tWINHTTP_PROXY_INFO[1], "proxychars", $sProxy)
    DllStructSetData($tWINHTTP_PROXY_INFO[1], "proxybypasschars", $sProxyBypass)
    Return $tWINHTTP_PROXY_INFO
EndFunc
Edited by Jos
added [ code ]
Link to comment
Share on other sites

Put your script in SciTE, translate the comments to english because they might help in understanding your script, run Tidy (CTRL-t) and Syntax check (CTRL-F5) on it until there are no errors, then post on the forum using [code][/code] tags (angle brackets in the toolbar just above the forum edit window).

You'll get more help if you take some effort to make your code readable to those who might like to.

:unsure:

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...