Самый первый этап в работе с вебом — отправка данных в ваше серверное приложение. И если парсинг десятка мелких строк можно доверить фреймворку, то как быть с загрузкой файлов?

Возьмем для примера PHP, хотя описанное справедливо и для 99% остальных языков и технологий. Допустим, мы хотим позволить пользователю загружать картинки на сайт, для этого делаем формочку с полем типа file и… Внешне все очень просто, всего-то изменилось несколько байт в форме и в коде, зато теперь вместо текста из форм можно работать с файлами! Но не всё так просто, вашему файлу надо сначала осесть где-то в /tmp/, пока запрос не придет полностью, ваш скрипт просто не получит управления и вы ничего не сможете с этим сделать. К примеру, вместо картинки, пользователь загрузил exe-файл, но вы узнаете об этом только после того, как загрузка будет окончательно завершена. Тем самым, злоумышленник на некоторое время может забить вам канал и время вашей дисковой подсистемы, делая вид, что загружает полезные файлы, а вы об этом даже не узнаете. Если перед сервером приложений стоит кеширующий сервер, то ситуация еще хуже: к примеру, nginx создает временные файлы, т.е. сначала запрос от пользователя осядет на диске, как только он завершится, то файл перечитывается и быстро отдается серверу приложений (в нашем случае php), где он сохраняется на диск ЕЩЕ раз. Итого тройное использование диска, даже если пользователю надо просто вывести сообщение «ты забыл ввести капчу».

Я уже не говорю о том, что более веселые вещи при таком подходе не сделать. Простая фича вроде «индикатора загрузки файла» становится недоступной. К более сложным примерам: Youtube показывает кадры из фильма, который еще только загружается, но до конца не загружен. Вы же не получите никакого управления (и даже уведомления!) до того, как весь фильм (2 гигабайта, к примеру) будет загружен. Вы даже не узнаете о том, что кто-то проел 1.5 гигабайта вашего диска, но потом закрыл браузер или нажал кнопку «обновить» в браузере, так ничего и не дождавшись.

Конечно, есть различные костыли разной степени кривости, которые позволяют решать типовые задачи, вроде «получение статистики запроса через json», реализуемые как модули веб-серверов, но такие вещи придется делать самостоятельно и/или тем самым привязываться к окружению, приложение перестает быть независимым и обрастает зависимостью от конкретных приложений и их библиотек.

Кеш


Кеши жизненно необходимы. Техника кеширования позволяет ускорить отзывчивость вашего сайта и снизить на него нагрузку, позволяя не делать однотипные операции для множества запросов. К примеру, сколько не делай 2+2, всегда будет 4, однако вычисление 2+2 занимает ресурсы сервера, гораздо выгоднее вычислить это значение 1 раз, при приходе первого посетителя, а потом где-то записать, дабы всем остальным пользователям выдавать этот готовый результат.

Не стоит путать это кеширование с http-заголовками, они имеют действие только на определенного клиента (в оригинале еще и на промежуточные прокси), в то время как кеширование на сервере призвано отдавать множеству пользователей одинаковый контент.

Увы, отдавать кеширование промежуточному серверу не выгодно, в случае малейшего обновления на странице, придется с нуля создавать страницу, а учитывая современные реалии, когда на странице много динамических элементов, то фактически каждая страница будет уникальной, а с другой стороны, запрос вида GET /somepage.html?someshit=12345 пробьет кеш и будет формирована новая страница, которая даже не будет учитывать этот параметр, но тем не менее, будут затраты на ее создание, чем опять же может воспользоваться злоумышленник. Поэтому промежуточные кеш-сервера сейчас мало кто использует и полагаться на них уже очень сложно.

Остается кешировать все внутри приложения, почти каждый фреймворк предоставляет как собственные костыли, так и готовые вроде всяких мемкешедов и тому подобного говна. Обычно начинающие разработчики просто кипятком писают когда узнают, что при генерации страницы можно сделать 500 запросов к мемкешеду и за это ничего не будет (в отличии от всеми любимого mysql). Как следствие, весь код покрывается обертками, которые сначала проверяют результат запроса в мемкешде, а потом уже лезут за результатом в mysql. Не спорю, ручной контроль за кешем необходим, но полностью ручной контроль приводит к возможным ошибкам, где кеширование можно просто забыть включить, что по закону подлости, будет критическим местом.

Интерфейсы


Какой интерфейс должен быть у сайта? Только не говорите, что зелененький.

Раньше как правило, представление сайта было едино и неделимо. Однако на крупных порталах встречались кнопочки «версия для печати», а то и вообще «wap-версия», которую впоследствии заменила «PDA-версия» — уже обычный HTML, только более простой. Хотя смотря где, если взять Twitter, то это единственная читабельная версия у него. Время шло и появилась потребность править сайты не только под принтеры и телефоны, но и под всякие айпады и холодильники с поддержкой HTML5. Естественно, что разработчиков это все залюбило, ведь им нужно было фактически делать по 10 версий одного сайта, и они решили сделать что-то универсальное. Эдакое API для сайта.

Что такое API — я не знаю. Честно, я не знаю. Обычно это какое-то говно, когда на сервер плюешься куском urlencoded string, а в ответ получаешь кусок json/xml/plain text, как оно повезет. Разумеется, никаких стандартов, даже примитивные типы данных могут быть чем угодно, пустой результат может тоже быть чем угодно, от null до "" (пустые кавычки), а то и вообще отсутствовать в результате. Хорошо если авторы прочитали про такое слово как REST и бросились его реализовывать, но на фоне всего остального оно не имеет никакого смысла. Функциональность тоже не ясна, если затребовав HTML-страничку мы можем получить все и сразу (последние новости, комментарии, лайки и т.д.), то сколько нам надо будет делать запросов в случае API — знает только автор этого API, вполне возможно, что комментарии получить можно будет, а вот лайки к ним — нет. Фактически, API — это способ разделить разработку клиента и сервера на совершенно различные команды разработчиков, слабо взаимодействующие друг с другом. И никакой речи в отношении полезности этого API быть не может.

А еще часто бывает, что для доступа к API требуется некий ключ. Ключи же зачастую можно получать бесплатно. Почему бы не получить такой ключ? Проблема в том, что это ведет нас к явному учету запросов, к некоторой внутренней бухгалтерии. А кто знает, когда автор захочет все это монетизировать? Вполне возможно, что через некоторое время бесплатные ключи отключат или сильно ограничат, предложив воспользоваться платным тарифом. А иногда и вообще, выдачу всех ключей приостанавливают, а обслуживание прекращают, даже на коммерческой основе, такое тоже бывает. Ну и зачем такое API? Мне проще стянуть страничку и распарсить ее регулярками, чем терпеть такое безобразие. Потому я почти никогда не пользуюсь этими вашими API, тем более я не собираюсь разбираться с их особенностями.

Комментарии (16)


  1. firedragon
    19.10.2018 17:32
    -3

    Скажите это владельцу сайта sysadmins.ru Петру.

    Там присутствует и не валидный html и названия топиков шифруются через AES (якобы защита от ботов) и всякое прочее. В общем минус вам за парсинг регулярками.


  1. impwx
    19.10.2018 17:33
    +2

    Понимаю боль автора, но от статьи ждал какого-то вывода, а вместо этого она закончилась истерикой.


  1. ookami_kb
    19.10.2018 17:49

    Слишком толсто.


    1. maximw
      20.10.2018 01:52

      Да классно же. Очень напомнило по стилю какой-то стнедап. Эдакий стендап-хабра-пост.


      1. ookami_kb
        20.10.2018 13:34

        Хм, а где тогда юмор?


        1. maximw
          20.10.2018 18:14

          Там же где и в средней руки стендапе — почти нигде.
          Просто представьте стендапера на сцене и прочитайте статью с подходящими интонациями и паузами.


  1. balexa
    19.10.2018 17:51
    +1

    Какой-то истеричный поток сознания. «все говнокодеры, а я дартаньян».


  1. zodchiy
    19.10.2018 17:53
    +2

    В нормальных языках и технологиях, картинки проверяются в памяти и никуда не сохраняются пока не проверяться на то, что это именно картинки. Не забить канал помогает правильная настройка, которая не даст загрузить большие файлы не только на стороне браузера, но и сервера. Проблемы с кэшем решают современные подходы (SPA и проч.) в кэше только скрипты, а остальное берется из API. Остальное просто хейтинг.


    1. demimurych
      19.10.2018 17:59
      -1

      В памяти говорите? А у Вас есть фотографы которые работают с RAW? Или монтажеры которые грузян монтажную колбасу?


      1. zodchiy
        19.10.2018 18:51
        +2

        Пост вроде о вебе, и о конкретном примере.


    1. qyk Автор
      22.10.2018 14:46

      Т.е. мне заливать в память гигабайтную картинку и только потом пытаться ее распарсить? И пока пользователь ее заливает, 2 часа этот гигабайт серверной памяти принадлежит только ему? Или мы прикроем задницу лимитом вида «не более 100кб на файл, 640х480 наше все», наплевав на пользователя? И да, расскажите как это сделать, так как файл (а точнее запрос) начинает записываться на диск еще на стадии декодинга запроса сервером. И никакая бизнес-логика не запускается, пока пользователь свой гигабайт не загрузит (ну, во времена CGI запускалась).


  1. Grox
    19.10.2018 20:32
    +1

    Возьмем для примера PHP, хотя описанное справедливо и для 99% остальных языков и технологий. Допустим, мы хотим позволить пользователю загружать картинки на сайт, для этого делаем формочку с полем типа file и…
    Так работает браузер и HTML, а серверные языки тут не при чём. Реализовать загрузку на файла с прогрессбаром можно уже очень много лет разными способами.

    Всё, что вы описали далее, это обычное поведение. Его можно изменить. Например есть такие модули, как nginx-upload-module. И вообще, это скорее относится к протоколу HTTP, чем к языкам, которые его обслуживают.


  1. leahch
    19.10.2018 21:10
    +2

    Возьмем к примеру java, хотя нет — ruby или go, хотя нет — PHP!
    1) При загрузке файла потоком, его можно никуда не сохранять! Он приходит потоком, который можно и остановить и оборвать, при этом еще раз — это не файл в /tmp, а поток непосредственно с клиентское приложение. Подозреваю, в PHP тоже можно получить именно поток, а не ссылку на уже загруженный файл, просто научитесь его готовить.
    2) Про кеширование. Используйте правильные шаблонизаторы, которые умеют кешировать кусочки, а не всю страницу, и если данные куска страницы не поменялись, то он просто возьмется из кеша уже отрендеренный. И да, всю страницу тоже можно. И да, PHP тоже так умеет, просто научитесь его готовить.
    3) Какое такое API? Вы о чем? Верстка на всем, что движется доступна в любом современном CSS фреймворке, начиная с bootstrap и заканчивая w3css, просто научитесь его готовить.

    В общем — Вам двойка за подготовку домашнего задания.


  1. Mikluho
    20.10.2018 10:40

    Автор любит устаревший веб?
    Когда надо было уместить хотя бы стартовую страницу сайта со всем её содержимым в 20-30 кб? Когда приходилось генерировать на сервере все страницы в десятке вариантов, ибо клиенты были разными, очень разными и dhtml почти никто не умел? Когда… много чего ещё можно перечислить такого, после чего современный веб — сказка наяву.
    Автор, похоже, попросту не разобрался с технологиями и у него болит. Но может уже пора повзрослеть? Выйти из детсадовского возраста? (Это отсылка к известному тесту про скамейку, краткое изложение вот тут: bash.im/quote/418579)
    Как уже было описано ранее — все «проблемы» или не проблемы или имеют решение. Я не скажу за php, но на .net уж точно :) И файлы без сохранения на диск и с прогрессбаром, и даже с проверкой содержимого до полной загрузки. И кэш на любой вкус и цвет, работающий ровно тогда, когда это надо. И API с внятной структурой и встроенной документацией. Что уж говорить про возможность универсализировано смаппить ajax запрос на запрос к БД, с валидацией, да через кэш, и с прозрачной проверкой прав пользователя…
    А может автор так странно изливает недовольство заполонившими веб рукожопами, к которым он сам себя не относит? Тогда почему бы прямо так не сказать?


  1. Tyusha
    21.10.2018 10:26

    Краткое содержание статьи, кому лень читать: «Раньше я тырил информацию с сайтов легко, а теперь злые веб-мастера ради удобства глупых юзеров всё делают через XHR, и у нас, парсеров, бомбит.»


  1. vin2809
    22.10.2018 08:18

    Прочитал до, точнее, еле дождался, конца статьи, но так и не увидел ответ на вопрос в заголовке "За что я не люблю современный веб".

    Содержание всех разделов больше похоже на легкий стёб на тему «Обо всем, что слышал». Если бы в конце были выводы, могла получиться (плохая или хорошая) статья. А так, увы…