Ошибка при загрузке страницы входа на сайте

219
21 мая 2018, 16:30

Пытаемся получить корректный ответ от веб-сервера:

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(ipAddress, 443));
NetworkStream networkStream = new NetworkStream(socket);
SslStream sslStream = new SslStream(networkStream);
sslStream.ReadTimeout = -1;
sslStream.WriteTimeout = -1;
sslStream.AuthenticateAsClient(host);
// Load login page.
sbRequest = new StringBuilder();
sbRequest.Append("GET /auth/login-page HTTP/1.1\r\n");
sbRequest.Append($"Host: {host}\r\n\r\n");
sslStream.Send(Encoding.UTF8.GetBytes(sbRequest.ToString()));
sslStream.Flush();
// Read web-server response.
System.Threading.Thread.Sleep(200);
// (read the first 1024 bytes - all headers and the page beginning)
byte[] data = new byte[1024];
sslStream.Read(data, 0, 1024);
Console.WriteLine(Encoding.UTF8.GetString(data));

Итог общения:

REQUEST:
--------------------------------------------------
GET /auth/login-page HTTP/1.1
Host: [host]
--------------------------------------------------
RESPONSE
--------------------------------------------------
HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Tue, 15 May 2018 17:35:40 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Vary: Cookie
Strict-Transport-Security: max-age=15768000
1f66
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta ...

Где, собственно, Content-Length? Что за "1f66"?..

Дабы проверить как это делает браузер (ведь у него же всё получается), посмотрел Fiddler'ом как сайт отвечает на его запросы:

REQUEST:
--------------------------------------------------
GET /auth/login-page HTTP/1.1
Host: [host]
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
--------------------------------------------------
RESPONSE:
--------------------------------------------------
HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Tue, 15 May 2018 16:59:29 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Vary: Accept-Encoding
Vary: Cookie
Strict-Transport-Security: max-age=15768000
Content-Length: 8992
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta ...

Сделал точно такой же запрос из своей программы, но ответ пришёл ещё хуже:

REQUEST:
--------------------------------------------------
GET /auth/login-page HTTP/1.1
Host: [host]
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
--------------------------------------------------
RESPONSE
--------------------------------------------------
HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Tue, 15 May 2018 17:44:32 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Vary: Cookie
Strict-Transport-Security: max-age=15768000
Content-Encoding: gzip
8fc
...

Кракозябры в конце. Видимо из-за Content-Encoding: gzip... Посылаем такой же запрос, а ответ приходить другой.

Answer 1

Вы получили ответ в кодировке chuncked, о чем сервер и сообщает вам в ответе:

Transfer-Encoding: chunked

Подробнее как это работает, можно прочитать например в вики.

Браузер сообщает серверу, что он умеет декодировать gzip:

Accept-Encoding: gzip, deflate, br

Поэтому сервер и присылает сжатый контент. В C# есть удобный класс System.IO.Compression.GZipStream, можете без проблем "разархивировать" сжатые данные.

Answer 2

При передаче в режиме chunked перед каждым фрагментом передается его размер в шестнадцатеричном виде. Соответственно, вместо Content Length нужно использовать это значение.

Браузер точно так же пишет. Мне в gzip приходит, а ему нет. Почему?

Когда вы указываете Accept-Encoding: gzip, deflate, br, вы указываете предпочтительные форматы для передачи. Сервер может выбрать другой формат, если он считает сжатие нецелесообразным или из-за перегрузки не может его выполнять. Нет правила, что на один и тот же запрос в разные моменты времени должен придти один и тот же ответ.

Из https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding

Even if both the client and the server supports the same compression algorithms, the server may choose not to compress the body of a response, if the identity value is also acceptable. Two common cases lead to this:

  • The data to be sent is already compressed and a second compression won't lead to smaller data to be transmitted.
  • This may the case with some image formats; The server is overloaded and cannot afford the computational overhead induced by the compression requirement. Typically, Microsoft recommends not to compress if a server use more than 80 % of its computational power.

Чтобы явно требовать передачу со сжатием, нужно указать что-то такое:

Accept-Encoding: deflate, gzip, *;q=0

Чтобы наоборот, требовать обязательной передачи без сжатия - такое:

Accept-Encoding: identity, *;q=0
READ ALSO
Вывод каталогов и файлов в один DataGrid

Вывод каталогов и файлов в один DataGrid

Суть такова, есть DataGrid и 2 списка с типом FileInfo и DirectoryInfo

197
Найти конечные координаты линии Line

Найти конечные координаты линии Line

Подскажите как найти конечные координаты линии после поворота

157
Программно разместить RadioButton в groupBox. c#

Программно разместить RadioButton в groupBox. c#

Требуется разместить несколько GroupBox и в них RadioButton, чтобы потом можно было к ним обращаться

167
Как найти в тексте слова с нечетным количеством букв и удалить из них среднюю букву?

Как найти в тексте слова с нечетным количеством букв и удалить из них среднюю букву?

Нужно на C# с помощью регулярных выражений в введенном тексте найти слова с нечетным количеством букв, а потом удалить из них среднюю букву

216