проверить ответ сервера php

Как получить HTTP код ответа удаленного веб-сервера из PHP?

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

Когда требуется получить HTTP код для заданной URL, то вы наверняка воспользуетесь PHP функцией get_headers($url). Дальше я расскажу о разных подводных камнях и возникающих попутных проблемах.

В первом приближении задача решается элементарно. У вас есть URL, вы запрашиваете только заголовки, т.к. вам не нужен сам документ. В заголовках можно найти и пропарсить стандартный ответ сервера, чтобы извлечь код ответа.

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

Домен не существует

Да такое бывает, когда введенный адрес не существует. Вернее не адрес, а доменное имя сайта. Запрос посылать некуда, а вы увидите (если не отключили вывод php warnings) что то вроде следующего:

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

PHP вернет пустые заголовки, из которых ничего не извлечь. Как можно обработать эту ситуацию?

Тут вы уже не увидите сообщений от PHP, а в случае невозможности определить адрес сервера — будет установлено какое то кастомное значение вместо HTTP кода, чтобы иметь возможность его обработать дальше.

Доменные имена с использованием национальных наборов символов.

Функция get_headers не настолько умна, чтобы переводить ваш http://россия.рф в http://xn--h1alffa9f.xn--p1ai200.

Если вы попытаетесь запросить заголовки без перевода в нужный вид, то прошлый пример выдаст вам загадочное ‘no response’. В то время как браузер без проблем откроет сайт, т.к. умеет переводить доменные имена, в которых используются местные национальные наборы символов, отличные от латиницы.

Для конвертации используем свободно распространяемую библиотеку idna_convert. Качайте архив, распаковывайте и подключайте в ваш код.

Источник

http_response_code

(PHP 5 >= 5.4.0, PHP 7, PHP 8)

http_response_code — Получает или устанавливает код ответа HTTP

Описание

Получает или задаёт коды ответов HTTP.

Список параметров

Возвращаемые значения

Примеры

Пример #1 Использование http_response_code() в окружении веб-сервера

// Берём текущий код и устанавливаем новый
var_dump ( http_response_code ( 404 ));

// Берём новый код
var_dump ( http_response_code ());
?>

Результат выполнения данного примера:

Пример #2 Использование http_response_code() в CLI

// Берём текущий код по умолчанию
var_dump ( http_response_code ());

// Устанавливаем код
var_dump ( http_response_code ( 201 ));

// Берём новый код
var_dump ( http_response_code ());
?>

Результат выполнения данного примера:

Смотрите также

User Contributed Notes 18 notes

If your version of PHP does not include this function:

For reference the error codes I got from PHP’s source code:

And how the current http header is sent, with the variables it uses:

Note that you can NOT set arbitrary response codes with this function, only those that are known to PHP (or the SAPI PHP is running on).

The following codes currently work as expected (with PHP running as Apache module):
200 – 208, 226
300 – 305, 307, 308
400 – 417, 422 – 424, 426, 428 – 429, 431
500 – 508, 510 – 511

Codes 0, 100, 101, and 102 will be sent as «200 OK».

Everything else will result in «500 Internal Server Error».

If you want to send responses with a freestyle status line, you need to use the `header()` function:

When setting the response code to non-standard ones like 420, Apache outputs 500 Internal Server Error.

This happens when using header(0,0,420) and http_response_code(420).
Use header(‘HTTP/1.1 420 Enhance Your Calm’) instead.

Note that the response code in the string IS interpreted and used in the access log and output via http_response_code().

Status codes as an array:

You can also create a enum by extending the SplEnum class.
/** HTTP status codes */
class HttpStatusCode extends SplEnum <
const __default = self :: OK ;

const SWITCHING_PROTOCOLS = 101 ;
const OK = 200 ;
const CREATED = 201 ;
const ACCEPTED = 202 ;
const NONAUTHORITATIVE_INFORMATION = 203 ;
const NO_CONTENT = 204 ;
const RESET_CONTENT = 205 ;
const PARTIAL_CONTENT = 206 ;
const MULTIPLE_CHOICES = 300 ;
const MOVED_PERMANENTLY = 301 ;
const MOVED_TEMPORARILY = 302 ;
const SEE_OTHER = 303 ;
const NOT_MODIFIED = 304 ;
const USE_PROXY = 305 ;
const BAD_REQUEST = 400 ;
const UNAUTHORIZED = 401 ;
const PAYMENT_REQUIRED = 402 ;
const FORBIDDEN = 403 ;
const NOT_FOUND = 404 ;
const METHOD_NOT_ALLOWED = 405 ;
const NOT_ACCEPTABLE = 406 ;
const PROXY_AUTHENTICATION_REQUIRED = 407 ;
const REQUEST_TIMEOUT = 408 ;
const CONFLICT = 408 ;
const GONE = 410 ;
const LENGTH_REQUIRED = 411 ;
const PRECONDITION_FAILED = 412 ;
const REQUEST_ENTITY_TOO_LARGE = 413 ;
const REQUESTURI_TOO_LARGE = 414 ;
const UNSUPPORTED_MEDIA_TYPE = 415 ;
const REQUESTED_RANGE_NOT_SATISFIABLE = 416 ;
const EXPECTATION_FAILED = 417 ;
const IM_A_TEAPOT = 418 ;
const INTERNAL_SERVER_ERROR = 500 ;
const NOT_IMPLEMENTED = 501 ;
const BAD_GATEWAY = 502 ;
const SERVICE_UNAVAILABLE = 503 ;
const GATEWAY_TIMEOUT = 504 ;
const HTTP_VERSION_NOT_SUPPORTED = 505 ;
>

Do not mix the use of http_response_code() and manually setting the response code header because the actual HTTP status code being returned by the web server may not end up as expected. http_response_code() does not work if the response code has previously been set using the header() function. Example:

( ‘HTTP/1.1 401 Unauthorized’ );
http_response_code ( 403 );
print( http_response_code ());
?>

The raw HTTP response will be (notice the actual status code on the first line does not match the printed http_response_code in the body):

HTTP/1.1 401 Unauthorized
Date: Tue, 24 Nov 2020 13:49:08 GMT
Server: Apache
Connection: Upgrade, Keep-Alive
Keep-Alive: timeout=5, max=100
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

I only tested it on Apache. I am not sure if this behavior is specific to Apache or common to all PHP distributions.

The note above from «Anonymous» is wrong. I’m running this behind the AWS Elastic Loadbalancer and trying the header(‘:’.$error_code. ) method mentioned above is treated as invalid HTTP.

The documentation for the header() function has the right way to implement this if you’re still on ( «HTTP/1.0 404 Not Found» );
?>

At least on my side with php-fpm and nginx this method does not change the text in the response, only the code.

// HTTP/1.1 404 Not Found
http_response_code ( 404 );

?>

The resulting response is HTTP/1.1 404 OK

http_response_code() does not actually send HTTP headers, it only prepares the header list to be sent later on.
So you can call http_reponse_code() to set, get and reset the HTTP response code before it gets sent.

http_response_code(500); // set the code
var_dump(headers_sent()); // check if headers are sent
http_response_code(200); // avoid a default browser page

http_response_code is basically a shorthand way of writing a http status header, with the added bonus that PHP will work out a suitable Reason Phrase to provide by matching your response code to one of the values in an enumeration it maintains within php-src/main/http_status_codes.h. Note that this means your response code must match a response code that PHP knows about. You can’t create your own response codes using this method, however you can using the header method.

1. Using http_response_code will cause PHP to match and apply a Reason Phrase from a list of Reason Phrases that are hard-coded into the PHP source code.

2. Because of point 1 above, if you use http_response_code you must set a code that PHP knows about. You can’t set your own custom code, however you can set a custom code (and Reason Phrase) if you use the header method.

It’s not mentioned explicitly, but the return value when SETTING, is the OLD status code.
e.g.
= http_response_code ();
$b = http_response_code ( 202 );
$c = http_response_code ();

Источник

get_headers

get_headers — Возвращает все заголовки из ответа сервера на HTTP-запрос

Описание

get_headers() возвращает массив с заголовками из ответа сервера на HTTP-запрос.

Список параметров

Если необязательный параметр associative установлен в ненулевое значение, get_headers() разберёт ответ сервера и установит ключи для возвращаемого массива.

Возвращаемые значения

Возвращает индексированный или ассоциативный массив с заголовками ответа или false при возникновении ошибки.

Список изменений

Примеры

Пример #1 Пример использования get_headers()

Результатом выполнения данного примера будет что-то подобное:

Пример #2 Пример использования запроса HEAD в функции get_headers()

Смотрите также

User Contributed Notes 27 notes

If the URL redirected and the new target is also redirected, we got the Locations in array. Also we got the HTTP codes in a number indexed values.

array
(
[0] => HTTP/1.1 302 Moved Temporarily

[Location] => Array
(
[0] => /test.php?id=2
[1] => /test.php?id=3
[2] => /test.php?id=4
)

[1] => HTTP/1.1 302 Moved Temporarily
[2] => HTTP/1.1 302 Moved Temporarily
[3] => HTTP/1.1 200 OK
)

In a typical situation we need only the landing page information, so here is a small code to get it:

How to check if a url points to a valid video

I know you’re not supposed to reference other notes, but sincere props to Nick at Innovaweb’s comment, for which I base this addition to his idea:

If you use that function, it will return a string, which is great if you are checking for only files that return 404, or 200, or whatnot. If you cast the string value to an integer, you can perform mathematical comparison on it.

if( intval ( get_http_response_code ( ‘filename.jpg’ )) 400 ) <
// File exists, huzzah!
>
?>

Rule of thumb is if the response is less than 400, then the file’s there, even if it doesn’t return 200.

if the URL does not exist, it returns incomplete headers, making the substring default to rubbish.

The integer value of rubbish is always 0. So your lower than 400 does not always means it exists!

To check URL validity, this has been working nicely for me:

If you don’t want to display Warning when get_headers() function fails, you can simply add at-sign (@) before it.

// in failure, Warning will be hidden and false returned
$withoutWarning = @ get_headers ( «http://www.some-domain.com» );

// in failure, Warning displays and false will be returned, too
$withWarning = get_headers ( «http://www.some-domain.com» );

Note that get_headers should not be used against a URL that was gathered via user input. The timeout option in the stream context only affects the idle time between data in the stream. It does not affect connection time or the overall time of the request.

(Unfortunately, this is not mentioned in the docs for the timeout option, but has been discussed in a number of code discussions elsewhere, and I have done my own tests to confirm the conclusions of those discussions.)

If you are publishing your code, even default_socket_timeout cannot be relied on to remedy this, because it is broken for the HTTPS protocol on many but the more recent versions of PHP: https://bugs.php.net/bug.php?id=41631

With get_headers accepting user input, it can be very easy for an attacker to make all of your PHP child processes become busy.

Instead, use cURL functions to get headers for a URL provided by the user and parse those headers manually, as CURLOPT_TIMEOUT applies to the entire request.

hey, i came across this afew weeks ago and used the function in an app for recording info about domains that my company owns, and found that the status this returns was wrong most of the time (400 bad request or void for sites that were clearly online). then looking into it i noticed the problem was that it wasn’t able to get the correct info about sites with redirections. but thats not the full problem because everything on my server was returning the wrong status too. i searched around on php.net for other info and found that fsockopen’s example worked better and only needed some tweeking.

heres the function i put together from it and a small change.

hope this’ll help someone else.

It should be noted that rather than returning «false» on failure, this function (and others) return a big phat WARNING that will halt your script in its tracks if you do not have error reporting /warning turned off.

Thats just insane! Any function that does something like fetch a URL should simply return false, without a warning, if the URL fails for whatever reason other than it is badly formatted.

The following code dose NOT work with PHP version 7.0.26 with my server.

Some other setting may be required?

Tried with website pages and path to local files.
The word ‘Finished’ is printed only.

Should be the same than the original get_headers():

I’ve noticed it.
Some Server will simply return the false reply header if you sent ‘HEAD’ request instead of ‘GET’. The ‘GET’ request header always receiving the most actual HTTP header instead of ‘HEAD’ request header. But If you don’t mind for a fast but risky method then ‘HEAD’ request is better for you.

aeontech, this the below change adds support for SSL connections. Thanks for the code!

I found that this function is the slowest in obtaining the headers of a page probably because it uses a GET request rather then a HEAD request. Over 10,000,000 trials of obtaining the headers of a page from a server i found the following (results in seconds).

cURL: Mean: 0.584127946. Sigma: 0.050581736.
fsocketopen: Mean: 0.622114251. Sigma: 0.263170424.
get_headers: Mean: 0.90375551. Sigma: 0.273823419.

cURL was the fastest with fsocketopens being the second fastest. I noticed as well that fsocketopen had some outliers where as cURL did not.

In some cases, you don’t want get_headers to follow redirects. For example, some of my servers can access a particular website, which sends a redirect header. The site it is redirected to, however, has me firewalled. I need to take the 302 redirected url, and do something to it to give me a new url that I *can* connect to.

The following will give you output similar to get_headers, except it has a timeout, and it doesn’t follow redirects:

Testing the validity of a URL that is preceded by one or more server redirects is tricky. There will be more than one status code returned and all but the first will be redirect codes.

This function will return an integer containing the three digit status code of the last code returned, which is what you want.

return (int) substr($value, strpos($value, ‘ ‘, 8) + 1, 3);
>

If getHeaders() fails, PHP will throw an error. Test the return value for === false.

/**
* Fetches all the real headers sent by the server in response to a HTTP request without redirects
*
* @link http://php.net/function.get_headers
* @link http://bugs.php.net/bug.php?id=50719
*/

For anyone reading the previous comments, here is code that takes into account all the previous suggestions and includes a bugfix, too.

In response to dotpointer’s modification of Jamaz’ solution.

if(! function_exists ( ‘get_headers’ )) <

Unfortunately there is still no useful output format to handle redirects.

This function will bring all non-broken headers into a usable format. Too bad it has to call the get_headers() funtion 2 times, but i dont see any other possibility right now.

Content-Type returns a value depending only on the extension and not the real MIME TYPE.

Источник

Как проверить код ответа сервера / узнать код ответа страницы

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

При обращении по URL-у, сервер отдает нам не только содержимое страницы, но и передает служебную информацию, например: код статуса HTTP. Прежде, чем перейти к проверке ответа сервера, предлагаю определиться с терминами.

Что такое код статуса HTTP?

Код статуса HTTP (или код ответа сервера) — трёхзначное число, которое обозначает определенный статус запрашиваемой страницы.

Пример:

Подробнее посмотреть значения кодов ответа сервера можно в этой статье.

Например:

В этой статье мы рассмотрим различные задачи, связанные с проверкой ответа сервера, а также поговорим о полезных инструментах, которые помогут нам решить их.

Проверить код ответа сервера страницы

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

Все довольно просто: необходимо вставить URL страницы и нажать кнопку “Проверить”.

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

Узнать код ответа сервера всех страниц сайта

Для пакетной проверки ответа сервера вышеизложенный сервис нам, к сожалению, не подойдет, поэтому воспользуемся десктопными приложениями Xenu или Spider, которые помогут пропарсить все страницы сайта и проверить код ответа всех страниц.

Получение статуса страниц в Xenu

В главном меню перейдем «File- Check URL». Введем адрес сайта и запустим проверку урлов на ответ сервера

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

Результат проверки статуса ответа сервера можно будет увидеть в колонке «Status».

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

Получение статуса страниц в Spider

Запускаем приложение, вводим URL. Результат смотрим в колонке “Статус”.

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

Массовая проверка страниц на код ответа сервера

Используется для проверки группы Url-ом нескольких сайтов или вполне конкретных страниц. В решении этой задаче нам поможет этот сервис. Вводим списком адреса.

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

Есть небольшое ограничение: максимальное количество Url-ов составляет 100 адресов.

Но это совсем не проблема. Я предлагаю вам решение, которое вы можете реализовать на вашем веб-сервере (необходимы небольшие знания PHP).

Рассмотрим функцию get_headers, которая возвращает все заголовки, посланные сервером в ответ на HTTP запрос.

Пример: Возвращает код ответа сервера заданного URL-а.

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

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

– Только качественный трафик из Яндекса и Google
– Понятная отчетность о работе и о планах работ
– Полная прозрачность работ

Источник

Проверка ответа сервера

Быстрый и удобный сервис по проверке кода ответа сервера с широким функционалом и расшифровкой HTTP-заголовков. Мобильная версия и кнопка быстрой проверки для удобства работы. Checkmy показывает ответ сервера по заданному URL, это поможет определить существование URL или корректность работы сайта в зависимости от кода, который отдает сервер.

Как проверить ответ сервера

Используйте кнопку быстрого доступа к сервису Checkmy для мгновенной проверки кода ответа сервера нужной страницы сайта.

1. Перетащите кнопку Checkmy на панель закладок своего браузера.

2. Зайдите на страницу сайта, которую хотите проверить.

3. Нажмите кнопку /Checkmy/ в панели закладок своего браузера.

В новой вкладке браузера откроется результат проверки ответа сервера страницы на которой вы находитесь.

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

Проверка кода ответа сервера

C помощью онлайн сервиса проверки кода ответа сервера вы можете проверить http заголовки, которые выдает сервер при запросе url адреса. Это может быть полезно для того, чтобы узнать включено ли сжатие контента на сервере, проверить исходный код страницы, узнать включена ли поддержка кеширования на сервере и получить другую полезную информацию из заголовков ответа сервера.
Что можно проверить в заголовках сервера:

Заголовки ответа сервера

Список популярных заголовков ответа сервера с пояснением их значений.

Content-Type

Описание формата передаваемого контента. Необходимо для корректного распознавания браузером.

Accept-Encoding

Перечень способов кодирования содержимого ответа при передаче.

Дата генерации передаваемого контента, используется время отвечающего сервера.

Expires

Дата предполагаемого истечения срока актуальности контента.

Last-Modified

Дата последней модификации контента.

If-Modified-Since

Дата, когда необходимо загружать контент, если он изменился с указанного момента.

Location

URL-адрес по которому клиенту следует перейти или URL созданного ресурса.

Server

Список названий и версий веб-сервера и его компонентов с комментариями.

Коды состояний http-сервера

Полный список кодов состояний http-сервера с расшифровкой значения.

200 OkЗапрос клиента обработан успешно и ответ сервера содержит затребованные данные.
201 CreatedЭтот код состояния используется в случае создания нового URI. Вместе с этим кодом результата сервер выдает заголовок Location, который содержит информацию о том, куда были помещены новые данные.
202 AcceptedЗапрос принят, но обрабатывается не сразу. В теле содержимого ответа сервера может быть дана дополнительная информация о данной транзакции. Гарантии того, что сервер в конечном итоге удовлетворит допустимым.
203 Non-Authoritative InformationИнформация в заголовке содержимого взята из локальной копии или у третьей стороны, а не с исходного сервера.
204 No ContentОтвет содержит код состояния и заголовок, но тело содержимого отсутствует. При получении этого ответа браузер не должен обновлять свой документ. Обработчик чувствительных областей изображений может возвращать этот код, когда пользователь щелкает на бесполезных или пустых участках изображения.
205 Reset ContentБраузер должен очистить форму, используемую в данной транзакции, для дополнительных входных данных. Полезен для CGI-приложений, требующих ввода данных.
206 Partial ContentСервер возвращает лишь часть данных затребованного объема. Используется в ответе на запрос с указанием заголовка Range. Сервер должен указать диапазон, включенный в ответ, в заголовке Content-Range.
300 Multiple ChoicesЗапрошенный URI обозначает более одного ресурса, например, документ переведенный на несколько языков. В теле ответа сервера может находиться перечень конкретных данных о том, как выбрать ресурс правильно.
301 Moved PermanentlyДокумент перемещен навсегда, новый адрес документа указывается в заголовке Location. Старый адрес больше не используется.
302 Moved TemporarilyДокумент перемещен временно, новый адрес документа указывается в заголовке Location. Сейчас нужно запросить документ по новому адресу, но в последствии документ будет доступен по старому адресу.
303 See OtherДокумент доступен также и по другому адресу, который указан в заголовке Location.
304 Not ModifiedЕсли при запросе используется заголовок lf-Modified-Since и документ не менялся с указанной даты, то сервер ответит данным кодом. Тело содержимого не посылается, и клиент должен использовать свою локальную копию.
305 Use ProxyДоступ к документу должен осуществляться через proxy-сервер, указанный в заголовке Location.
500 Internal Server ErrorВнутренняя ошибка конфигурации сервера или одного из его компонентов. Запрос не может быть обработан.
501 Not ImplementedЗапрос не может быть выполнен сервером.
502 Bad GatewayСервер получил недопустимый ответ от другого сервера или прокси-сервера.
503 Service UnavailableСлужба временно недоступна, если известно время восстановления, то будет выдан заголовок Retry-After.
504 Gateway Time-outШлюз или сервер превысил время ожидания ответа и ожидание прервано.
505 HTTP Version not supportedСервер не поддерживает версию протокола HTTP, использованную в запросе.

Ответы на популярные вопросы

Проверьте ответы на популярные вопросы, возможно вы найдете ответ на свой вопрос.

По-умолчанию Checkmy использует User Agent пользователя, то есть ваш. Если вы хотите его изменить, то можете выбрать любой другой из соответствующего выпадающего списка.

Да, сервис поддерживает IDN-домены и для их проверки не требуется переводить имя домена в punycode. Просто введите введите адрес вашего кириллического домена и проверьте http-код ответа сервера.

Да, конечно, вы можете использовать Checkmy на мобильных устройствах для проверки http-ответа сервера, он быстро загружается и прекрасно выглядит.

проверить ответ сервера php. Смотреть фото проверить ответ сервера php. Смотреть картинку проверить ответ сервера php. Картинка про проверить ответ сервера php. Фото проверить ответ сервера php

Что делает Checkmy

Он позволяет быстро и удобно проверить заголовки ответа http-сервера, опционально поддерживает заголовки Accept-Encoding и If-Modified-Since.

Кому нужно проверять HTTP-заголовки

Корректность HTTP-заголовков ответа сервера необходимо проверять разработчиками, вебмастерам и SEO-оптимизаторам.

Наши проекты

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *