Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: east  
Дата: 30.03.15 07:54
Оценка:
Всем привет!
Начал разбираться с подключаемыми протоколами. Нужен был фильтр. Но после статьи Asynchronous Pluggable Protocol
Автор(ы): Вадим Макутин
Дата: 12.06.2004
Разбирается создание и работа собственного интернет-протокола, приводится пример приложения, использующего такой протокол.
осознал насколько это интересная штука. Можно брать данные откуда хочешь, а WebBrowser их отобразит. Однако в статье не описано как проинформировать WebBrowser в каком формате передаются данные. Поэтому прошу помочь разобраться со следующими вопросами:
1. Как сообщить WebBrowser, что данные это страница html или картинка png, или xml? В протоколе http это делает соответствующий заголовок — Content-type. Как передать такой заголовок (да и другие заголовки http-протокола) в WebBrowser?
2. Как получить полностью заголовок запроса http-протокола, который отправляет WebBrowser и POST, PUT данные? Тут я докопался, что эту информацию можно узнать через IInternetBindInfo, но например, GetBindString не возвращает полный заголовок и некоторые отдельные, такие как UserAgent или версию OS. Что касается GetBindInfo, то выяснил, что POST и PUT данные находятся в поле stgmedData структуры BINDINFO, а дальше темный лес.
Re: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: Aniskin  
Дата: 30.03.15 14:55
Оценка:
Здравствуйте, east, Вы писали:

E>1. Как сообщить WebBrowser, что данные это страница html или картинка png, или xml? В протоколе http это делает соответствующий заголовок — Content-type. Как передать такой заголовок (да и другие заголовки http-протокола) в WebBrowser?


IProtocolSink.ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, MIMEType). IProtocolSink передается в IInternetProtocolRoot.Start

E>2. Как получить полностью заголовок запроса http-протокола, который отправляет WebBrowser и POST, PUT данные? Тут я докопался, что эту информацию можно узнать через IInternetBindInfo, но например, GetBindString не возвращает полный заголовок и некоторые отдельные, такие как UserAgent или версию OS. Что касается GetBindInfo, то выяснил, что POST и PUT данные находятся в поле stgmedData структуры BINDINFO, а дальше темный лес.


Imho, WebBrowser не обязан отдавать строку BINDSTRING_USERAGENT. Всякие UserAgent-ы — это специфика http(s). У тебя ведь не http(s)?
Re[2]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: east  
Дата: 31.03.15 14:17
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Здравствуйте, east, Вы писали:


E>>1. Как сообщить WebBrowser, что данные это страница html или картинка png, или xml? В протоколе http это делает соответствующий заголовок — Content-type. Как передать такой заголовок (да и другие заголовки http-протокола) в WebBrowser?


A>IProtocolSink.ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, MIMEType). IProtocolSink передается в IInternetProtocolRoot.Start


Спасибо!
Главное уже в каком-то коде видел это и не разобрался.

E>>2. Как получить полностью заголовок запроса http-протокола, который отправляет WebBrowser и POST, PUT данные? Тут я докопался, что эту информацию можно узнать через IInternetBindInfo, но например, GetBindString не возвращает полный заголовок и некоторые отдельные, такие как UserAgent или версию OS. Что касается GetBindInfo, то выяснил, что POST и PUT данные находятся в поле stgmedData структуры BINDINFO, а дальше темный лес.


A>Imho, WebBrowser не обязан отдавать строку BINDSTRING_USERAGENT. Всякие UserAgent-ы — это специфика http(s). У тебя ведь не http(s)?


Это не критично, я для общего образования спрашивал, т.к. не понятно зачем вводить некоторые перечисления, если их не использовать. Могу ошибаться, но для ИЕ и контролов на основе ИЕ заголовок устанавливается в интернет-сессии из реестра.
Спасибо за помощь.
Re[3]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: Aniskin  
Дата: 01.04.15 10:25
Оценка:
Здравствуйте, east, Вы писали:

A>>Imho, WebBrowser не обязан отдавать строку BINDSTRING_USERAGENT. Всякие UserAgent-ы — это специфика http(s). У тебя ведь не http(s)?


E>Это не критично, я для общего образования спрашивал, т.к. не понятно зачем вводить некоторые перечисления, если их не использовать.


Не проверял, но возможно если ты напишешь и перекроешь стандартный http протокол, то тебе будут передаваться UserAgent-ы и прочая атрибутика http протокола.
Re: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: east  
Дата: 14.04.15 13:43
Оценка:
В общем начал делать протокол и столкнулся с такой ситуацией. В методе Start загружаю данные в буфер и сообщаю браузеру, что есть данные. В методе Read отдаю данные. Однако после нескольких вызовов Read браузер вновь создает объект протокола и по новому вызывает метод Start. Получается, что данные полностью не загрузились в браузер и началась новая сессия. Что может быть?
Может кто подскажет хорошую инфу по асинхронным протоколам, чтобы все мелочи описывались.
Re[2]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: Aniskin  
Дата: 14.04.15 18:20
Оценка:
Здравствуйте, east, Вы писали:

E>В методе Start загружаю данные в буфер и сообщаю браузеру, что есть данные. В методе Read отдаю данные. Однако после нескольких вызовов Read браузер вновь создает объект протокола и по новому вызывает метод Start. Получается, что данные полностью не загрузились в браузер и началась новая сессия. Что может быть?


А что и в какой последовательности передаешь в ProtocolSink.ReportProgress?
Re[3]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: east  
Дата: 16.04.15 11:50
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Здравствуйте, east, Вы писали:


E>>В методе Start загружаю данные в буфер и сообщаю браузеру, что есть данные. В методе Read отдаю данные. Однако после нескольких вызовов Read браузер вновь создает объект протокола и по новому вызывает метод Start. Получается, что данные полностью не загрузились в браузер и началась новая сессия. Что может быть?


A>А что и в какой последовательности передаешь в ProtocolSink.ReportProgress?


Просто передаю mime-тип. Код примерно такой, точно не помню, т.к. проект на другом компьютере.
HRESULT STDMETHODCALLTYPE CMyProtocol::Start(
  /* [in] */ LPCWSTR szUrl, 
  /* [in] */ IInternetProtocolSink __RPC_FAR  *pOIProtSink,
  /* [in] */ IInternetBindInfo __RPC_FAR *pOIBindInfo,
  /* [in] */ DWORD grfPI,
  /* [in] */ DWORD dwReserved)
{
  ATLTRACE(_T("CMyProtocol::Start ()\n"));

  //загружаем данные
  m_BD.Load(szUrl);

  pOIProtSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, m_BD.m_sMimeType);
  //информируем о том что есть что отображать
  pOIProtSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, m_BD.m_DataLen);
  return S_OK;
}
Re[4]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: Aniskin  
Дата: 16.04.15 18:05
Оценка:
Здравствуйте, east, Вы писали:

E>Код примерно такой.


BindInfo может содержать флаг BINDF_NEEDFILE. В этом случае требуется создавать временный файл, в который нужно записывать передаваемые данные. Я обычно пишу в кэш Эксплорера (CreateUrlCacheEntry/CommitUrlCacheEntry).
Re[5]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: east  
Дата: 17.04.15 04:34
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>BindInfo может содержать флаг BINDF_NEEDFILE. В этом случае требуется создавать временный файл, в который нужно записывать передаваемые данные. Я обычно пишу в кэш Эксплорера (CreateUrlCacheEntry/CommitUrlCacheEntry).



Т.е. записать данные в кеш и не сообщать, что данные готовы, чтобы не вызывался Read? Или как?
Хотя судя по статье
Автор(ы): Вадим Макутин
Дата: 12.06.2004
Разбирается создание и работа собственного интернет-протокола, приводится пример приложения, использующего такой протокол.
все должно быть просто, как я сделал. Все работает нормально когда данных мало, но когда их 20К, появляется ситуация описанная выше.
Где вообще можно почитать о работе асинхронного протокола по подробней? Может у кого есть код нормально работающего протокола? А то в сети нашел пару вариантов, ничего там не понял и разбираться нет возможности, т.к. не работают, выдают ошибки.
Re[6]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: Aniskin  
Дата: 17.04.15 06:16
Оценка:
Здравствуйте, east, Вы писали:

E>Т.е. записать данные в кеш и не сообщать, что данные готовы, чтобы не вызывался Read?


Сообщить, что есть файл вызовом ProtocolSink.ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE), и при поступлении данных писать их в этот файл. При этом если Read вызывается, то и отдавать полученные данные.

Я делаю следующие вызовы:

ProtocolSink.ReportProgress(BINDSTATUS_FINDINGRESOURCE, PWideChar(Url));
ProtocolSink.ReportProgress(BINDSTATUS_CONNECTING, PWideChar(Url));
ProtocolSink.ReportProgress(BINDSTATUS_SENDINGREQUEST, PWideChar(Url));
ProtocolSink.ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, PWideChar(Response.MIMEType));
ProtocolSink.ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE, PWideChar(Stream.FileName));
ProtocolSink.ReportData(BSCF_FIRSTDATANOTIFICATION, 0, 0);
ProtocolSink.ReportData(BSCF_INTERMEDIATEDATANOTIFICATION, Saved, Size); // Много раз
ProtocolSink.ReportData(BSCF_LASTDATANOTIFICATION or BSCF_DATAFULLYAVAILABLE, Saved, Size);
ProtocolSink.ReportResult(S_OK, Response.Status, nil);

Все это происходит из отдельного потока.
Re[7]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: east  
Дата: 20.04.15 08:57
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Сообщить, что есть файл вызовом ProtocolSink.ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE), и при поступлении данных писать их в этот файл. При этом если Read вызывается, то и отдавать полученные данные.


A>Я делаю следующие вызовы:


A>ProtocolSink.ReportProgress(BINDSTATUS_FINDINGRESOURCE, PWideChar(Url));

A>ProtocolSink.ReportProgress(BINDSTATUS_CONNECTING, PWideChar(Url));
A>ProtocolSink.ReportProgress(BINDSTATUS_SENDINGREQUEST, PWideChar(Url));
A>ProtocolSink.ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, PWideChar(Response.MIMEType));
A>ProtocolSink.ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE, PWideChar(Stream.FileName));
A>ProtocolSink.ReportData(BSCF_FIRSTDATANOTIFICATION, 0, 0);
A>ProtocolSink.ReportData(BSCF_INTERMEDIATEDATANOTIFICATION, Saved, Size); // Много раз
A>ProtocolSink.ReportData(BSCF_LASTDATANOTIFICATION or BSCF_DATAFULLYAVAILABLE, Saved, Size);
A>ProtocolSink.ReportResult(S_OK, Response.Status, nil);

A>Все это происходит из отдельного потока.


В общем вот это я вынес отдельный поток
static UINT LoadSrc(LPVOID pParam)
{
    THREAD* pLoad = (THREAD*)pParam;
    pLoad->pSink->ReportProgress(BINDSTATUS_CONNECTING, pLoad->sUrl);
    pLoad->pSink->ReportProgress(BINDSTATUS_SENDINGREQUEST, pLoad->sUrl);
    pLoad->pSink->ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA, pLoad->sUrl);
    pLoad->BD->Send(pLoad->sUrl);
    CString ct = pLoad->BD->GetRawHeader(_T("Content-Type:"));
    pLoad->pSink->ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, ct);
    pLoad->pSink->ReportData(BSCF_DATAFULLYAVAILABLE, 0, pLoad->BD->m_ulDataLen);
    pLoad->pSink->ReportResult(S_OK,0,NULL);
    return 0;
}


Как и следовало ожидать, ничего не изменилось. Все равно браузер два раза вызывает метод Start в разных потоках. Наблюдается такая ситуация, если в Start просто вернуть S_OK, то браузер виснет. Если вызвать ReportData или ReportResult, то Start вызывается второй раз в другом потоке и следовательно вызываются все остальные методы и как следствие страница не найдена и ошибки.
Может у кого есть рабочий код асинхронного протокола?
Re[8]: Asynchronous Pluggable Protocol http-заголовки, post и put данные
От: east  
Дата: 20.04.15 14:22
Оценка:
E>В общем вот это я вынес отдельный поток
E>
E>static UINT LoadSrc(LPVOID pParam)
E>{
E>    THREAD* pLoad = (THREAD*)pParam;
E>    pLoad->pSink->ReportProgress(BINDSTATUS_CONNECTING, pLoad->sUrl);
E>    pLoad->pSink->ReportProgress(BINDSTATUS_SENDINGREQUEST, pLoad->sUrl);
E>    pLoad->pSink->ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA, pLoad->sUrl);
E>    pLoad->BD->Send(pLoad->sUrl);
E>    CString ct = pLoad->BD->GetRawHeader(_T("Content-Type:"));
E>    pLoad->pSink->ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, ct);
E>    pLoad->pSink->ReportData(BSCF_DATAFULLYAVAILABLE, 0, pLoad->BD->m_ulDataLen);
E>    pLoad->pSink->ReportResult(S_OK,0,NULL);
E>    return 0;
E>}

E>


E>Как и следовало ожидать, ничего не изменилось. Все равно браузер два раза вызывает метод Start в разных потоках. Наблюдается такая ситуация, если в Start просто вернуть S_OK, то браузер виснет. Если вызвать ReportData или ReportResult, то Start вызывается второй раз в другом потоке и следовательно вызываются все остальные методы и как следствие страница не найдена и ошибки.

E>Может у кого есть рабочий код асинхронного протокола?

Как не стыдно признавать, но ошибка у меня была в другом месте. Неправильно получал mime-тип. Вот из-за этого и вылазили ошибки. Вышеприведенный код работает нормально, пока глюков не замечал. Можно выводить его как в отдельный поток, так и в методе Start.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.