diff --git a/Source/Alcinoe.HTTP.Client.WinINet.pas b/Source/Alcinoe.HTTP.Client.WinINet.pas index ded0359e5..7dd596451 100644 --- a/Source/Alcinoe.HTTP.Client.WinINet.pas +++ b/Source/Alcinoe.HTTP.Client.WinINet.pas @@ -158,6 +158,7 @@ TALWinInetHTTPClient = class(TALHTTPClient) FInetConnect: HINTERNET; FOnStatus: TAlWinInetHTTPClientStatusEvent; FIgnoreSecurityErrors: Boolean; + FAllowHttp2Protocol: Boolean; procedure SetAccessType(const Value: TALWinInetHttpInternetOpenAccessType); procedure SetInternetOptions(const Value: TAlWininetHTTPClientInternetOptionSet); procedure SetOnStatus(const Value: TAlWinInetHTTPClientStatusEvent); @@ -193,6 +194,7 @@ TALWinInetHTTPClient = class(TALHTTPClient) property InternetOptions: TAlWininetHTTPClientInternetOptionSet read FInternetOptions write SetInternetOptions default [wHttpIo_Keep_connection]; property OnStatus: TAlWinInetHTTPClientStatusEvent read FOnStatus write SetOnStatus; property IgnoreSecurityErrors: Boolean read FIgnoreSecurityErrors write FIgnoreSecurityErrors; + property AllowHttp2Protocol: Boolean read FAllowHttp2Protocol write FAllowHttp2Protocol; end; implementation @@ -246,6 +248,7 @@ constructor TALWinInetHTTPClient.Create; FInternetOptions := [wHttpIo_Keep_connection]; RequestHeader.UserAgent := 'Mozilla/3.0 (compatible; TALWinInetHTTPClient)'; FIgnoreSecurityErrors := False; + FAllowHttp2Protocol := False; end; {**************************************} @@ -378,17 +381,36 @@ procedure TALWinInetHTTPClient.Connect; if whttpIo_Offline in InternetOptions then Result := result or INTERNET_FLAG_OFFLINE; end; + Function InternalGetInternetSecurityFlags: DWord; + Begin + Result := 0; + if FURLScheme = INTERNET_SCHEME_HTTPS then begin + if FIgnoreSecurityErrors then begin + Result := Result or SECURITY_SET_MASK; + end else begin + if whttpIo_IGNORE_CERT_CN_INVALID in InternetOptions then + Result := Result or SECURITY_FLAG_IGNORE_CERT_CN_INVALID; + if whttpIo_IGNORE_CERT_DATE_INVALID in InternetOptions then + Result := Result or SECURITY_FLAG_IGNORE_CERT_DATE_INVALID; + end; + end; + end; + const AccessTypeArr: Array[TALWinInetHttpInternetOpenAccessType] of DWord = (INTERNET_OPEN_TYPE_DIRECT, INTERNET_OPEN_TYPE_PRECONFIG, INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, INTERNET_OPEN_TYPE_PROXY); +const + HTTP_PROTOCOL_FLAG_HTTP2 = 2; + INTERNET_OPTION_ENABLE_HTTP_PROTOCOL = 148; var LSetStatusCallbackResult: PFNInternetStatusCallback; - ProxyStr: AnsiString; - ProxyPtr: PAnsiChar; - + LProxyStr: AnsiString; + LProxyPtr: PAnsiChar; + LUserAgent: AnsiString; + LOption: DWORD; begin { Yes, but what if we're connected to a different Host/Port?? } { So take advantage of a cached handle, we'll assume that @@ -399,20 +421,22 @@ procedure TALWinInetHTTPClient.Connect; { Also, could switch to new API introduced in IE4/Preview2} if InternetAttemptConnect(0) <> ERROR_SUCCESS then System.SysUtils.Abort; - ProxyStr := InternalGetProxyServerName; - if ProxyStr <> '' then begin - ProxyPtr := PAnsiChar(ProxyStr); + LProxyStr := InternalGetProxyServerName; + if LProxyStr <> '' then begin + LProxyPtr := PAnsiChar(LProxyStr); end else begin - ProxyPtr := nil; + LProxyPtr := nil; end; + LUserAgent := RequestHeader.UserAgent; + {init FInetRoot} FInetRoot := InternetOpenA( - PAnsiChar(RequestHeader.UserAgent), + PAnsiChar(LUserAgent), AccessTypeArr[FAccessType], - ProxyPtr, + LProxyPtr, InternalGetProxyBypass, - InternalGetInternetOpenFlags); + InternalGetInternetOpenFlags or InternalGetInternetSecurityFlags); CheckError(not Assigned(FInetRoot)); try @@ -423,6 +447,13 @@ procedure TALWinInetHTTPClient.Connect; CheckError(LSetStatusCallbackResult = pointer(INTERNET_INVALID_STATUS_CALLBACK)); end; + {Enable HTTP/2 protocol (for Windows 10 and later)} + if FAllowHttp2Protocol and (FURLScheme = INTERNET_SCHEME_HTTPS) then begin + LOption := HTTP_PROTOCOL_FLAG_HTTP2; + // ignore any errors, because this protocol is optional + InternetSetOptionA(FInetRoot, INTERNET_OPTION_ENABLE_HTTP_PROTOCOL, Pointer(@LOption), SizeOf(LOption)); + end; + {init FInetConnect} FInetConnect := InternetConnectA( FInetRoot, @@ -466,8 +497,6 @@ function TALWinInetHTTPClient.Send( Result := 0; if whttpIo_CACHE_IF_NET_FAIL in InternetOptions then Result := result or INTERNET_FLAG_CACHE_IF_NET_FAIL; if whttpIo_HYPERLINK in InternetOptions then Result := result or INTERNET_FLAG_HYPERLINK; - if whttpIo_IGNORE_CERT_CN_INVALID in InternetOptions then Result := result or INTERNET_FLAG_IGNORE_CERT_CN_INVALID; - if whttpIo_IGNORE_CERT_DATE_INVALID in InternetOptions then Result := result or INTERNET_FLAG_IGNORE_CERT_DATE_INVALID; if whttpIo_IGNORE_REDIRECT_TO_HTTP in InternetOptions then Result := result or INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP; if whttpIo_IGNORE_REDIRECT_TO_HTTPS in InternetOptions then Result := result or INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS; if whttpIo_KEEP_CONNECTION in InternetOptions then Result := result or INTERNET_FLAG_KEEP_CONNECTION; @@ -507,11 +536,11 @@ function TALWinInetHTTPClient.Send( end; var LNumberOfBytesWritten: DWord; - LDwFlags: DWORD; - LBuffLen: Cardinal; LBuffSize, LLen: cardinal; LINBuffer: INTERNET_BUFFERSA; LBuffer: TMemoryStream; + LAccept: AnsiString; + LReferrer: AnsiString; LAcceptTypes: array of PAnsiChar; LHeader: AnsiString; LOption: DWord; @@ -521,8 +550,11 @@ function TALWinInetHTTPClient.Send( { Connect } Connect; + LAccept := RequestHeader.Accept; + LReferrer := RequestHeader.Referer; + SetLength(LAcceptTypes, 2); - LAcceptTypes[0] := PAnsiChar(RequestHeader.Accept); + LAcceptTypes[0] := PAnsiChar(LAccept); LAcceptTypes[1] := nil; Result := HttpOpenRequestA( @@ -530,23 +562,12 @@ function TALWinInetHTTPClient.Send( InternalGetHttpOpenRequestVerb, PAnsiChar(FURLPath), InternalGetHttpProtocolVersion, - PAnsiChar(requestHeader.Referer), + PAnsiChar(LReferrer), Pointer(LAcceptTypes), InternalGetHttpOpenRequestFlags, DWORD_PTR(Self)); CheckError(not Assigned(Result)); try - - if FIgnoreSecurityErrors and (FURLScheme = INTERNET_SCHEME_HTTPS) then begin - LBuffLen := SizeOf(LDwFlags); - CheckError(not InternetQueryOptionA(Result, INTERNET_OPTION_SECURITY_FLAGS, Pointer(@LDwFlags), LBuffLen)); - LDwFlags := LDwFlags or - SECURITY_FLAG_IGNORE_REVOCATION or - SECURITY_FLAG_IGNORE_UNKNOWN_CA or - SECURITY_FLAG_IGNORE_WRONG_USAGE; - CheckError(not InternetSetOptionA(Result, INTERNET_OPTION_SECURITY_FLAGS, Pointer(@LDwFlags), SizeOf(LDwFlags))); - end; - { Timeouts } if ConnectTimeout > 0 then begin LOption := ConnectTimeout;