
N-ART 2018 №1

Крупный вариант по клику
Возобновляем мысленный проект Димы
N-ART
Итак, что такое N-ART, это типа арт-журнал, где типа эксперты выбирают типа произведения искусства для одной цели — опубликовать их на нашем сайте. Критериев отбора всего 2:
1. Нам понравилось
2. Произведение нигде не было опубликовано.
Политика участия. Можно присылать свои работы каким угодно образом, лучше всего по почте или лично, тогда мы их отсканируем (сфотографируем) и отдадим оригинал обратно (вышлем письмом).
Политика редакции. Мы не получаем с публикации денег. Если кто-то из авторов хочет деньги, то он может приписать, что ему нужен донат. Весь донат для автора будет отправлен автору. Мы не берем процентов.
На остальные заебы похуй, весь цифровой контент, попавший к нам распространяется по лицензии Хекса
Сегодня у нас произведение Длиннопанка из города К.
Опечатка по Фрейду

Linux, curl, обнаружение и анализ ошибок HTTP. Улучшаем скрипт.
В первой части я показал, как просто обнаружить ошибки HTTP при работе с curl
. Но на самом деле, подход, использованный в скрипте, немного неправильный:
Клиент может не знать все коды состояния, но он обязан отреагировать в соответствии с классом кода. В настоящее время выделено пять классов кодов состояния.
Т.е. объясняя по рабоче-крестьянски, не только код 200 может свидетельствовать об успешном завершении запроса, а другие коды, кроме явных клиентских или серверных ошибок, могут требовать от нас каких-либо действий.
Вообще, коды ответа HTTP разделены на 5 классов:
1xx
— информационные
2xx
— успешное завершение
3xx
— требуется переопределение
4xx
— ошибка, допущенная со стороны клиента
5xx
— ошибка, допущенная со стороны сервера
Вот и модифицируем наш скрипт в соответствии со стандартом.
В общем, надо из кода ответа HTTP извлечь первую цифру, и, соответственно прореагировать. Привожу часть скрипта, ответственного за более подробную реакцию на код ответа HTTP:
curl -o $SAVEFILE $1 -D $HEADERDUMP >/dev/null 2>/dev/null EXITCODE=$? if [ $EXITCODE -ne 0 ]; then echo "CURL error $EXITCODE" else HTTPSTATUS=`cat $HEADERDUMP|head -1|awk '{print $2}'` #get HTTP status code HTTPSTATUSMESS=`cat $HEADERDUMP|head -1|cut -d ' ' -f 3- HTTPSTATUSID=`echo $HTTPSTATUS|cut -c 1` #get first char status code case "$HTTPSTATUSID" in 1 ) echo -n "Informational: ";; 2 ) echo -n "Success: ";; 3 ) echo -n "Redirection: ";; 4 ) echo -n "Client Error: ";; 5 ) echo -n "Server Error: ";; * ) echo -n "Unknow status: ";; esac echo "$HTTPSTATUS $HTTPSTATUSMESS" fi
Жирным шрифтом выделена строка, в которой мы получаем этот самый класс кода возврата.
Курсивом — строка, где мы получаем пояснения текстовые пояснения к коду ответа.
Используемая в процессе анализа утилита cut
, в первом случае, позволяет нам вывести в переменную все символы после с третьего пробела.
Перед первым у нас версия протокола http, потом код ошибки, а потом пояснение, которое может содержать несколько пробелов, поэтому awk
тут не подходит.
cut
так же может работать с текстовыми данными, в которых есть разделители, например пробелы, или же с отдельными символами, как в той строке кода, что выделена жирным — так мы можем извлечь первую цифру из кода ответа.
Дальнейший анализ осуществляется с помощью оператора case
Расширенный анализ кодов состояния HTTP:
На Pastebin
На Github
PHP скрипт для проверки:
На Pastebin
На Github
Краткий справочник по командам curl и wget Копия
Утилита cut
Коды статуса HTTP
Оператор case
curl в Linux, ошибка 404, обнаружение и использование кодов ответа HTTP
Итак, возникла следующая задача — определить, когда curl
получил вменяемые данные от http-сервера, а когда нет. В общем, и самом распространенном случае, задача сводится к тому, чтобы определить, отдал ли нам сервер запрашиваемый файл, или отобразил «страница не найдена».
Впрочем, это работает и для других возможных кодов ответа.
Ясно, что сервер, на наш запрос GET
может ответить, как возвратив нам запрашиваемую страницу, так и отправив код, например, 404 (не найдено)
, и возвратив страницу-заглушку для этого случая. Так вот, на уровне скрипта bash или скрипта php необходимо проанализировать ответ сервера, чтобы не выдать пользователю вместо ожидаемых данных, всяческую лабуду. Далее я рассматриваю исключительно консольную Linux-утилиту curl
. Для php, синтаксис, по-моему, отличается.
Есть страница, которую мы хотим получить: http://example.org/page.html
, сохранить ее в файл page.html
и есть curl
, команда будет такая:
curl -o "page.html" http://example.org/page.html
Если страница на месте, то мы получим ее, и ничего анализировать не требуется.
Если же нет, то от большинства web-серверов мы получим страницу-заглушку, например такую, но никакой ошибки при этом.
Как же быть:
Проверяем код ошибки самого curl
, если нет связи с сетью, URL неправильный, или задан неподдерживаемый curl
протокол, если так, то мы получим соответствующий код возврата, наподобие:
curl: (1) Protocol htt not supported or disabled in libcurl
А вот если адрес правильный, и никакой ошибки в адресе или соединении нет, то код возврата не сработает, нам самим придется думать дальше.
Надо получить код ответа HTTP!
Сделать это можно, если получить отдельно заголовки ответа сервера, и после их проанализировать. Благо, для этого никакого страшного колдунства не требуется, достаточно указать утилите curl
опцию -D
(т.е. dump
) и файл, куда выгружать заголовки.
Покажу это на примере конкретного скрипта:
#!/bin/bash HEADERDUMP="/tmp/headerdump.txt" SAVEFILE="/tmp/httpfile" HTTPSTATUS="" curl -o $SAVEFILE $1 -D $HEADERDUMP >/dev/null 2>/dev/null EXITCODE=$? if [ $EXITCODE -ne 0 ]; then echo "CURL error $EXITCODE" else HTTPSTATUS=`cat $HEADERDUMP|head -1|awk '{print $2}'` if [ "$HTTPSTATUS" == "200" ];then echo "OK" else echo "HTTP error $HTTPSTATUS" fi fi
заводим 3 переменные
HEADERDUMP="/tmp/headerdump.txt"
— файл, в который будем получать заголовки
SAVEFILE="/tmp/httpfile"
— файл с сервера, который мы хотим получить
HTTPSTATUS=""
— переменная для статуса (состояния) HTTP
curl -o $SAVEFILE $1 -D $HEADERDUM
пытаемся скачать нужный файл (получить страницу):
-o
«имя_файла» — куда сохранять результат
$1
— внутренняя переменная, первый параметр скрипта, при вызове его с командной строки. В своем скрипте надо заменить на свой случай.
можно добавить >/dev/null 2>/dev/null
— для красоты, чтоб не вылезали сообщения о процессе и ошибках.
-D <файл>
— файл, куда будем копировать заголовки
Файл headerdump.txt
выглядит примерно так:
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Fri, 30 Mar 2018 00:17:23 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.33
Link:
Set-Cookie: quick_chat_alias=Anon_240883; path=/
Upgrade: h2,h2c
Vary: Accept-Encoding,User-Agent
В первой строке — интересующая нас информация. Версия протокола (не интересно), код ответа (вот он) и информационное сообщение (не особо надо).
Вычленяем код:
HTTPSTATUS=`cat $HEADERDUMP|head -1|awk '{print $2}'`
1. Берем первую строчку (head -1
)
2. Сохраняем в переменную 2-е значение после пробела (разделитель пробел): awk '{print $2}'
Дальше можно анализировать:
if [ "$HTTPSTATUS" == "200" ];then echo "OK" else echo "HTTP error $HTTPSTATUS" fi

Также, впрочем, можно поступить и для анализа запросов POST, вот тестовый скрипт php для отладки подобных возможностей и скрипт bash

Пример с запросом GET
Пример с запросом GET на Гитхаб
Пример с запросом POST
Пример с запросом POST на Гитхаб