Zazhir 0 Posted February 22, 2023 I'm trying to make a request of type Get, for a simple API, which performs the query of unique codes of companies. I tried several ways to make this request, but all of them lead me to the following error error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version or this one error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version I upgraded from Indy component to the lateste version, current 10.6.20 and am using Delphi XE6. Below is one of the functions I did, but that doesn't bring me anything in the request response, and gives me the erros bellow: function TfrmAttAreaExterno.searchData02; var URL, response: String; jsonStreamRetorno, jsonStreamEnvio: TStringStream; SSLIO: TIdSSLIOHandlerSocketOpenSSL; strm: TMemoryStream; Error: TStringList; begin memo01.Clear(); URL := 'https://www.receitaws.com.br/v1/cnpj/27865757000102'; strm := TMemoryStream.Create; try IdHTTP01.AllowCookies := True; IdHTTP01.HandleRedirects := True; IdHTTP01.ProxyParams.BasicAuthentication := False; IdHTTP01.ProxyParams.ProxyPort := 0; IdHTTP01.Request.Connection := 'Keep-Alive'; IdHTTP01.Request.ContentLength := -1; IdHTTP01.Request.ContentType := 'application/x-www-form-urlencoded'; IdHTTP01.Request.Accept := 'text/html, application/xhtml+xml, image/jxr, */*'; IdHTTP01.Request.AcceptEncoding := 'gzip, deflate'; IdHTTP01.Request.AcceptLanguage := 'pt-BR'; IdHTTP01.Request.BasicAuthentication := False; IdHTTP01.Request.Host := 'img.discogs.com'; IdHTTP01.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like ' + 'Gecko'; SSLIO := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP01); SSLIO.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2]; SSLIO.SSLOptions.Mode := sslmUnassigned; SSLIO.SSLOptions.VerifyMode := [sslvrfPeer, sslvrfFailIfNoPeerCert, sslvrfClientOnce]; SSLIO.SSLOptions.VerifyDepth := 0; try idHttp01.IOHandler:= SSLIO; response := idHttp01.Get(URL); memo01.Text := response; except on E: Exception do begin ShowMessage(E.Message); end; end; except on E: Exception do begin ShowMessage(E.Message); end; end; end; Please, any help would be appreciated! I just run of the ideas to what might be causing this issue. Plus, I just run over all the internet, and tried every single solution that looks like was going to help me.... Share this post Link to post
KodeZwerg 54 Posted February 22, 2023 If your current problem is just that you can not download a file, with the Windows API it works like shown: program Project11; {$APPTYPE CONSOLE} {$R *.res} uses Winapi.Windows, Winapi.WinInet, System.SysUtils; const oneKB = DWORD(1024); procedure ParseURL(const lpszUrl: string; var Host, Resource: string); var lpszScheme : array[0..Pred(INTERNET_MAX_SCHEME_LENGTH)] of Char; lpszHostName : array[0..Pred(INTERNET_MAX_HOST_NAME_LENGTH)] of Char; lpszUserName : array[0..Pred(INTERNET_MAX_USER_NAME_LENGTH)] of Char; lpszPassword : array[0..Pred(INTERNET_MAX_PASSWORD_LENGTH)] of Char; lpszUrlPath : array[0..Pred(INTERNET_MAX_PATH_LENGTH)] of Char; lpszExtraInfo : array[0..Pred(oneKB)] of Char; lpUrlComponents : TURLComponents; begin ZeroMemory(@lpszScheme, SizeOf(lpszScheme)); ZeroMemory(@lpszHostName, SizeOf(lpszHostName)); ZeroMemory(@lpszUserName, SizeOf(lpszUserName)); ZeroMemory(@lpszPassword, SizeOf(lpszPassword)); ZeroMemory(@lpszUrlPath, SizeOf(lpszUrlPath)); ZeroMemory(@lpszExtraInfo, SizeOf(lpszExtraInfo)); ZeroMemory(@lpUrlComponents, SizeOf(TURLComponents)); lpUrlComponents.dwStructSize := SizeOf(TURLComponents); lpUrlComponents.lpszScheme := lpszScheme; lpUrlComponents.dwSchemeLength := SizeOf(lpszScheme); lpUrlComponents.lpszHostName := lpszHostName; lpUrlComponents.dwHostNameLength := SizeOf(lpszHostName); lpUrlComponents.lpszUserName := lpszUserName; lpUrlComponents.dwUserNameLength := SizeOf(lpszUserName); lpUrlComponents.lpszPassword := lpszPassword; lpUrlComponents.dwPasswordLength := SizeOf(lpszPassword); lpUrlComponents.lpszUrlPath := lpszUrlPath; lpUrlComponents.dwUrlPathLength := SizeOf(lpszUrlPath); lpUrlComponents.lpszExtraInfo := lpszExtraInfo; lpUrlComponents.dwExtraInfoLength := SizeOf(lpszExtraInfo); InternetCrackUrl(PChar(lpszUrl), Length(lpszUrl), ICU_DECODE or ICU_ESCAPE, lpUrlComponents); Host := lpszHostName; Resource := lpszUrlPath; end; function GetWinInetError(ErrorCode:Cardinal): string; const winetdll = 'wininet.dll'; var Len: Integer; Buffer: PChar; begin Len := FormatMessage( FORMAT_MESSAGE_FROM_HMODULE or FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_ARGUMENT_ARRAY, Pointer(GetModuleHandle(winetdll)), ErrorCode, 0, @Buffer, SizeOf(Buffer), nil); try while (Len > 0) and {$IFDEF UNICODE}(CharInSet(Buffer[Len - 1], [#0..#32, '.'])) {$ELSE}(Buffer[Len - 1] in [#0..#32, '.']) {$ENDIF} do Dec(Len); SetString(Result, Buffer, Len); finally LocalFree(HLOCAL(Buffer)); end; end; function GetRemoteFileSize(const AURL: string; const AShowError: Boolean; out AFileSize: Int64): Boolean; const sUserAgent = 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101'; var hInet : HINTERNET; hConnect : HINTERNET; hRequest : HINTERNET; lpdwBufferLength: DWORD; lpdwReserved : DWORD; ServerName: string; Resource: string; ErrorCode : Cardinal; LFileSize: Int64; begin ParseURL(AUrl, ServerName, Resource); Result := False; AFileSize := -1; hInet := InternetOpen(PChar(sUserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); if (hInet = nil) then begin ErrorCode := GetLastError; if AShowError then raise Exception.Create(Format('InternetOpen Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end; try hConnect := InternetConnect(hInet, PChar(ServerName), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0); if ((hConnect = nil) and AShowError) then begin ErrorCode := GetLastError; raise Exception.Create(Format('InternetConnect Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end; try hRequest := HttpOpenRequest(hConnect, PChar('HEAD'), PChar(Resource), nil, nil, nil, 0, 0); if (hRequest <> nil) then begin try lpdwBufferLength := SizeOf(LFileSize); lpdwReserved := 0; if ((not HttpSendRequest(hRequest, nil, 0, nil, 0)) and AShowError) then begin ErrorCode := GetLastError; raise Exception.Create(Format('HttpOpenRequest Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end; if ((not HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER, @LFileSize, lpdwBufferLength, lpdwReserved)) and AShowError) then begin ErrorCode := GetLastError; raise Exception.Create(Format('HttpQueryInfo Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end else begin AFileSize := LFileSize; Result := (AFileSize > 0); end; finally InternetCloseHandle(hRequest); end; end else if AShowError then begin ErrorCode := GetLastError; raise Exception.Create(Format('HttpOpenRequest Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end; finally InternetCloseHandle(hConnect); end; finally InternetCloseHandle(hInet); end; end; function Download(const AURL, AFileName: string): Boolean; const BufferSize = oneKB; var hSession, hURL: HInternet; Buffer: array[1..BufferSize] of Byte; BufferLen: DWORD; F: File; BytesLoaded, BytesTotal, BytesCalc: Int64; begin Result := False; if (not GetRemoteFileSize(AURL, True, BytesTotal)) then Exit; hSession := InternetOpen('', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ; // Establish the secure connection InternetConnect (hSession, PChar(AURL), INTERNET_DEFAULT_HTTPS_PORT, PChar(''), PChar(''), INTERNET_SERVICE_HTTP, 0, 0); try hURL := InternetOpenURL(hSession, PChar(AURL), nil, 0, INTERNET_FLAG_RELOAD, 0); BytesLoaded := 0; try AssignFile(f, AFileName); Rewrite(f,1); try repeat InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) ; BlockWrite(f, Buffer, BufferLen); if (BytesTotal > 0) then begin Inc(BytesLoaded, BufferLen); BytesCalc := (BytesLoaded * 100 div BytesTotal); end; until BufferLen = 0; finally CloseFile(f) ; Result := True; end; finally InternetCloseHandle(hURL); end finally InternetCloseHandle(hSession); end; end; begin try Download('https://www.receitaws.com.br/v1/cnpj/27865757000102', ExtractFilePath(ParamStr(0)) + 'file.json'); { TODO -oUser -cConsole Main : Insert code here } except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Share this post Link to post
Zazhir 0 Posted February 23, 2023 11 hours ago, KodeZwerg said: If your current problem is just that you can not download a file, with the Windows API it works like shown: program Project11; {$APPTYPE CONSOLE} {$R *.res} uses Winapi.Windows, Winapi.WinInet, System.SysUtils; const oneKB = DWORD(1024); procedure ParseURL(const lpszUrl: string; var Host, Resource: string); var lpszScheme : array[0..Pred(INTERNET_MAX_SCHEME_LENGTH)] of Char; lpszHostName : array[0..Pred(INTERNET_MAX_HOST_NAME_LENGTH)] of Char; lpszUserName : array[0..Pred(INTERNET_MAX_USER_NAME_LENGTH)] of Char; lpszPassword : array[0..Pred(INTERNET_MAX_PASSWORD_LENGTH)] of Char; lpszUrlPath : array[0..Pred(INTERNET_MAX_PATH_LENGTH)] of Char; lpszExtraInfo : array[0..Pred(oneKB)] of Char; lpUrlComponents : TURLComponents; begin ZeroMemory(@lpszScheme, SizeOf(lpszScheme)); ZeroMemory(@lpszHostName, SizeOf(lpszHostName)); ZeroMemory(@lpszUserName, SizeOf(lpszUserName)); ZeroMemory(@lpszPassword, SizeOf(lpszPassword)); ZeroMemory(@lpszUrlPath, SizeOf(lpszUrlPath)); ZeroMemory(@lpszExtraInfo, SizeOf(lpszExtraInfo)); ZeroMemory(@lpUrlComponents, SizeOf(TURLComponents)); lpUrlComponents.dwStructSize := SizeOf(TURLComponents); lpUrlComponents.lpszScheme := lpszScheme; lpUrlComponents.dwSchemeLength := SizeOf(lpszScheme); lpUrlComponents.lpszHostName := lpszHostName; lpUrlComponents.dwHostNameLength := SizeOf(lpszHostName); lpUrlComponents.lpszUserName := lpszUserName; lpUrlComponents.dwUserNameLength := SizeOf(lpszUserName); lpUrlComponents.lpszPassword := lpszPassword; lpUrlComponents.dwPasswordLength := SizeOf(lpszPassword); lpUrlComponents.lpszUrlPath := lpszUrlPath; lpUrlComponents.dwUrlPathLength := SizeOf(lpszUrlPath); lpUrlComponents.lpszExtraInfo := lpszExtraInfo; lpUrlComponents.dwExtraInfoLength := SizeOf(lpszExtraInfo); InternetCrackUrl(PChar(lpszUrl), Length(lpszUrl), ICU_DECODE or ICU_ESCAPE, lpUrlComponents); Host := lpszHostName; Resource := lpszUrlPath; end; function GetWinInetError(ErrorCode:Cardinal): string; const winetdll = 'wininet.dll'; var Len: Integer; Buffer: PChar; begin Len := FormatMessage( FORMAT_MESSAGE_FROM_HMODULE or FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_ARGUMENT_ARRAY, Pointer(GetModuleHandle(winetdll)), ErrorCode, 0, @Buffer, SizeOf(Buffer), nil); try while (Len > 0) and {$IFDEF UNICODE}(CharInSet(Buffer[Len - 1], [#0..#32, '.'])) {$ELSE}(Buffer[Len - 1] in [#0..#32, '.']) {$ENDIF} do Dec(Len); SetString(Result, Buffer, Len); finally LocalFree(HLOCAL(Buffer)); end; end; function GetRemoteFileSize(const AURL: string; const AShowError: Boolean; out AFileSize: Int64): Boolean; const sUserAgent = 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101'; var hInet : HINTERNET; hConnect : HINTERNET; hRequest : HINTERNET; lpdwBufferLength: DWORD; lpdwReserved : DWORD; ServerName: string; Resource: string; ErrorCode : Cardinal; LFileSize: Int64; begin ParseURL(AUrl, ServerName, Resource); Result := False; AFileSize := -1; hInet := InternetOpen(PChar(sUserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); if (hInet = nil) then begin ErrorCode := GetLastError; if AShowError then raise Exception.Create(Format('InternetOpen Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end; try hConnect := InternetConnect(hInet, PChar(ServerName), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0); if ((hConnect = nil) and AShowError) then begin ErrorCode := GetLastError; raise Exception.Create(Format('InternetConnect Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end; try hRequest := HttpOpenRequest(hConnect, PChar('HEAD'), PChar(Resource), nil, nil, nil, 0, 0); if (hRequest <> nil) then begin try lpdwBufferLength := SizeOf(LFileSize); lpdwReserved := 0; if ((not HttpSendRequest(hRequest, nil, 0, nil, 0)) and AShowError) then begin ErrorCode := GetLastError; raise Exception.Create(Format('HttpOpenRequest Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end; if ((not HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH or HTTP_QUERY_FLAG_NUMBER, @LFileSize, lpdwBufferLength, lpdwReserved)) and AShowError) then begin ErrorCode := GetLastError; raise Exception.Create(Format('HttpQueryInfo Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end else begin AFileSize := LFileSize; Result := (AFileSize > 0); end; finally InternetCloseHandle(hRequest); end; end else if AShowError then begin ErrorCode := GetLastError; raise Exception.Create(Format('HttpOpenRequest Error %d Description %s', [ErrorCode, GetWinInetError(ErrorCode)])); end; finally InternetCloseHandle(hConnect); end; finally InternetCloseHandle(hInet); end; end; function Download(const AURL, AFileName: string): Boolean; const BufferSize = oneKB; var hSession, hURL: HInternet; Buffer: array[1..BufferSize] of Byte; BufferLen: DWORD; F: File; BytesLoaded, BytesTotal, BytesCalc: Int64; begin Result := False; if (not GetRemoteFileSize(AURL, True, BytesTotal)) then Exit; hSession := InternetOpen('', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ; // Establish the secure connection InternetConnect (hSession, PChar(AURL), INTERNET_DEFAULT_HTTPS_PORT, PChar(''), PChar(''), INTERNET_SERVICE_HTTP, 0, 0); try hURL := InternetOpenURL(hSession, PChar(AURL), nil, 0, INTERNET_FLAG_RELOAD, 0); BytesLoaded := 0; try AssignFile(f, AFileName); Rewrite(f,1); try repeat InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) ; BlockWrite(f, Buffer, BufferLen); if (BytesTotal > 0) then begin Inc(BytesLoaded, BufferLen); BytesCalc := (BytesLoaded * 100 div BytesTotal); end; until BufferLen = 0; finally CloseFile(f) ; Result := True; end; finally InternetCloseHandle(hURL); end finally InternetCloseHandle(hSession); end; end; begin try Download('https://www.receitaws.com.br/v1/cnpj/27865757000102', ExtractFilePath(ParamStr(0)) + 'file.json'); { TODO -oUser -cConsole Main : Insert code here } except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. I don't want to download it, i just want the response of the request that i send to the api Share this post Link to post
KodeZwerg 54 Posted February 23, 2023 Than not save, make it a string or whatever you need, as file is just for demo reasons. @Zazhir Share this post Link to post
Zazhir 0 Posted February 23, 2023 The thing is, the error occurs when i pass the method GET(). So I don't have anything to save, or not save, because a don't have a response coming from the request. Share this post Link to post
Remy Lebeau 1394 Posted February 23, 2023 22 hours ago, Zazhir said: I tried several ways to make this request, but all of them lead me to the following error error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version or this one error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version I was able to connect to your specified URL using a web browser with TLS 1.2, and it received a response just fine. So you should be able to get a similar response using Indy with TLS 1.2, too. Have you tried using a packet sniffer, like Wireshark, to look at the actual TLS handshake that TIdSSLIOHandlerSocketOpenSSL is sending, to make sure it is really attempting to use TLS 1.2, and not say TLS 1.0 instead? Which version of the OpenSSL DLLs are you using, exactly? Does Indy's IsOpenSSL_TLSv1_2_Available() function in the IdSSLOpenSSLHeaders unit return True or False when the error occurs? 22 hours ago, Zazhir said: Below is one of the functions I did, but that doesn't bring me anything in the request response, and gives me the erros bellow: Offhand, that code looks ok, as far as setting up the SSLIOHandler, though I do have a few comments (not related to the TLS error) about the rest of the code: Why are you setting the Request.ContentType and Request.ContentLength properties when you are not sending any data to the server? Why are you setting the Request.Accept property, instead of using the default? Both values include '*/*', so you are not really gaining anything, especially since the server's response is JSON, which is not specified in either value, so caught by '*/*' anyway. Why are you setting the Request.Host property to a different hostname than is specified in the URL? Do not set the Request.AcceptEncoding manually, let TIdHTTP manage that for you. If you want to support compressed responses, you need to assign a compressor component to the TIdHTTP.Compressor property, in which case TIdHTTP will then set the Request.AcceptEncoding property based on the compressor's actual capabilities. 1 Share this post Link to post