При первом вызове TIdHTTP.Get()
событие OnVerifyPeer
видит сертификат Fiddler SSL / TLS вместо Google, поэтому он отклоняет сертификат, и основное сокетное соединение заканчивается закрытием.
Однако, в IOHandler InputBuffer
остались непрочитанные данные (примерно 162 байта зашифрованных данных). По проекту метод TIdIOHandlerStack.Connected()
возвращает True, пока есть непрочитанные данные, доступные для выполнения операций чтения, даже если нет физического соединения с сокетом.
Итак, что в итоге происходитво время второго вызова TIdHTTP.Get()
происходит следующее:
TIdHTTP
знает, что он обменивается данными через HTTPS через прокси-сервер и что он делает новый HTTP-запрос к тому же Googleсервер через тот же прокси, что и предыдущий вызов TIdHTTP.Get()
.Таким образом, TIdHTTP
проверяет Connected()
, чтобы увидеть, подключен ли он к прокси-серверу, и видит, что Connected()
изначально имеет значение True, поэтому он принимает решение пропустить новый запрос CONNECT
и действовать так, как если бы он отправлялновый HTTP-запрос по существующему прокси-соединению.
Однако, поскольку базовый сокет был отключен, TIdHTTP
должен установить новое сокет-соединение с Fiddler.При подготовке к новому HTTP-запросу InputBuffer
очищается.Connected()
проверяется снова и теперь имеет значение False, поэтому TIdHTTP
устанавливает новое сокетное соединение с Fiddler.Это новое сокетное соединение изначально не зашифровано (для IOHandler PassThrough
установлено значение True), поэтому последующее CONNECT
не будет зашифровано (но этот раздел кода не знает, что TIdHTTP
уже решил пропустить CONNECT
).
TIdHTTP
продолжает отправку запроса GET
в Fiddler в незашифрованном виде.
Fiddler кэширует свои туннели TLS в течение периодавремя, и поэтому он повторно использует существующий туннель в Google, пересылая незашифрованный GET
как есть в Google по соединению TLS, а затем перенаправляет ответ в незашифрованном виде обратно в TIdHTTP
.
Итак, в конечном счете, здесь есть три проблемы (я открыл билет в системе отслеживания проблем Indy ):
TIdHTTP
не очищаетсяInputBuffer
когда происходит сбой, который требует закрытия основного сокета.Простым решением этой проблемы является очистка InputBuffer
метода *1059* от любых существующих данных, прежде чем делать что-либо еще.Таким образом, он видит, что соединение действительно разорвано, прежде чем решить, что делать с CONNECT
.Теперь я проверил это исправление в репозитории Indy SVN и проверил, работает ли оно в вашем сценарии.
TIdHTTP
принимает решение отправить или пропустить CONNECT
слишком рано,прежде чем он знает, что он делает с базовым сокетом.Это потребует некоторой перезаписи внутренней логики TIdHTTP
, поэтому она будет отложена до более поздней версии Indy.
Fiddler пересылает незашифрованные данные туда и обратно черезранее зашифрованный туннель.С этим ничего не поделаешь в TIdHTTP
.