Как отправить JSON-данные на сервер

Огром­ный про­ект у нас впе­ре­ди. Ско­ро мы будем делать мене­джер шаб­ло­нов тек­ста, кото­рый смо­жет хра­нить наши бес­цен­ные дан­ные не локаль­но на ком­пью­те­ре, а на сер­ве­ре.

Для это­го мы уже сде­ла­ли рабо­чий про­то­тип при­ло­же­ния, а потом разо­бра­лись с поня­ти­ем JSON. Теперь попро­бу­ем отпра­вить дан­ные на сер­вер.

Как это устроено

Если мы хотим хра­нить дан­ные на сер­ве­ре и отправ­лять их туда в любой момент, нам нуж­но дей­ство­вать так:

  1. Собрать дан­ные в JSON-формат.
  2. Упа­ко­вать их в спе­ци­аль­ный запрос.
  3. Встро­ен­ны­ми сред­ства­ми JavaScript отпра­вить этот запрос на сер­вер по нуж­но­му адре­су.
  4. Что­бы наш запрос был при­нят, по это­му адре­су на сер­ве­ре дол­жен нахо­дить­ся скрипт, кото­рый уме­ет рабо­тать с таки­ми запро­са­ми.
  5. А что­бы сер­вер в прин­ци­пе отве­чал на какие-то запро­сы, нам нуж­но его это­му обу­чить.

Пер­вые три пунк­та сде­ла­ем на кли­ен­те — нашей HTML-странице, а скрипт и настрой­ки — на сер­ве­ре. Скрипт будем писать на PHP, поэто­му, если не зна­е­те, что это и как с этим рабо­тать, — почи­тай­те.

Что­бы было про­ще, мы отпра­вим и обра­бо­та­ем на сер­ве­ре совсем малень­кий JSON — в нём все­го две пары «имя: зна­че­ние», но даже со слож­ным запро­сом всё будет рабо­тать так же.

Готовим HTML-страницу

У нас будет очень про­стая стра­ни­ца, пото­му что самое важ­ное сей­час — научить­ся рабо­тать с JSON-форматом, а кра­со­ту наве­дём поз­же.

На стра­ни­це нам пона­до­бят­ся:

  • заго­ло­вок;
  • два поля вво­да, что­бы вы мог­ли вве­сти туда любые дан­ные и убе­дить­ся, что отправ­ка рабо­та­ет;
  • кноп­ка, кото­рая отправ­ля­ет JSON на сер­вер;
  • место для выво­да резуль­та­та — там мы выве­дем то, что при­шлёт нам сер­вер в ответ.

Мы сра­зу под­клю­чим jQuery, что­бы в скрип­те напря­мую обра­щать­ся к полям вво­да и месту для выво­да резуль­та­та. А ещё зара­нее зада­дим синий цвет для выво­да отве­та от сер­ве­ра — так мы сра­зу отли­чим дан­ные на стра­ни­це от того, что нам отве­тил сер­вер.

На язы­ке HTML это будет так:

<!DOCTYPE html>
<html>
<head>
  <title>
    Отправляем JSON-данные на сервер
  </title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body style="text-align:center;" id="body">
  <!-- заголовок -->
  <h1> Простая форма для проверки работы JSON </h1>
  <!-- делаем форму с полями ввода -->
  <p>
    <input type="text" id="name" placeholder="Ваше имя">
    <input type="text" id="lastname" placeholder="и фамилия">
    <!-- по нажатию на эту кнопку данные уйдут на сервер -->
    <button onclick="sendJSON()">Проверить JSON</button>
    <!-- а вот тут они появятся снова, но уже после обработки сервером -->
  <p class="result" style="color:blue"></p>
  </p>
</body>
</html>
Внеш­ний вид очень про­стой, что­бы про­ве­рить рабо­то­спо­соб­ность всей систе­мы

Отправляем данные на сервер

Обыч­но, что­бы отпра­вить дан­ные на сер­вер, нуж­но делать запрос. Вы нажи­ма­е­те кноп­ку на стра­ни­це, бра­у­зер ухо­дит думать, ждёт отве­та сер­ве­ра и рису­ет вам новую стра­ни­цу в соот­вет­ствии с этим отве­том. Гру­бо гово­ря, запрос на сер­вер застав­ля­ет вашу стра­ни­цу пере­за­гру­жать­ся.

К сча­стью, инже­не­ры дав­но при­ду­ма­ли, как отправ­лять дан­ные на сер­вер, не пере­за­гру­жая стра­ни­цу. Для это­го исполь­зу­ют JavaScript.

Что­бы отпра­вить запрос, нам пона­до­бит­ся встро­ен­ный объ­ект XMLHttpRequest(). Вот как мы вво­дим его в повест­во­ва­ние:

// создаём новый экземпляр запроса XHR let xhr = new XMLHttpRequest();

Для запро­са нам нуж­но знать адрес, куда будем отправ­лять наш JSON — это и есть адрес наше­го скрип­та, кото­рый мы напи­шем поз­же. Мы будем писать его на PHP, поэто­му зара­нее можем при­ду­мать ему имя и адрес, где он будет лежать: http://mihailmaximov.ru/projects/json/json.php.

// адрес, куда мы отправим нашу JSON-строку url = "http://mihailmaximov.ru/projects/json/json.php";

Когда мы зна­ем адрес, мы можем открыть соеди­не­ние, что­бы сер­вер был готов при­нять наши дан­ные. Это зна­чит, что мы пока ниче­го цен­но­го туда не посы­ла­ем, а про­сто пре­ду­пре­жда­ем сер­вер, что ско­ро что-то при­ле­тит:

// открываем соединение. url — это переменная с нашим адресом xhr.open("POST", url, true);

Теперь напи­шем заго­ло­вок запро­са, что­бы сер­вер пони­мал, какие дан­ные мы ему при­шлём и как ему их обра­ба­ты­вать. Так как у нас JSON, то это и про­пи­шем в заго­лов­ке:

 // устанавливаем заголовок — выбираем тип контента, который отправится на сервер, в нашем случае мы явно пишем, что это JSON setRequestHeader("Content-Type", "application/json");

Чуть ниже сра­зу про­пи­шем пове­де­ние скрип­та на слу­чай отве­та сер­ве­ра. Сер­вер дол­жен обра­бо­тать наши дан­ные, вер­нуть ответ, а мы долж­ны этот ответ пой­мать и выве­сти на стра­ни­цу:

// когда придёт ответ на наше обращение к серверу, мы его обработаем здесь
xhr.onreadystatechange = function () {
  // если запрос принят и сервер ответил, что всё в порядке
  if (xhr.readyState === 4 && xhr.status === 200) {
    // выводим то, что ответил нам сервер — так мы убедимся, что данные он получил правильно
    result.innerHTML = this.responseText;
  }
};

Послед­нее, что нам оста­лось сде­лать, — выта­щить наши вве­дён­ные дан­ные из полей, собрать из них JSON и отпра­вить на сер­вер:

 // преобразуем наши данные JSON в строку       var data = JSON.stringify({ "name": name.value, "lastname": lastname.value });       // когда всё готово, отправляем JSON на сервер       xhr.send(data);
Готовый скрипт на странице

<!-- скрипт, который обработает нажатие на кнопку и отправит данные на сервер -->
<script>
  // эта функция сработает при нажатии на кнопку
  function sendJSON() {
    // с помощью jQuery обращаемся к элементам на странице по их именам
    let name = document.querySelector('#name');
    let lastname = document.querySelector('#lastname');
    // а вот сюда мы поместим ответ от сервера
    let result = document.querySelector('.result');
    // создаём новый экземпляр запроса XHR
    let xhr = new XMLHttpRequest();
    // адрес, куда мы отправим нашу JSON-строку
    let url = "http://mihailmaximov.ru/projects/json/json.php";
    // открываем соединение
    xhr.open("POST", url, true);
    // устанавливаем заголовок — выбираем тип контента, который отправится на сервер, в нашем случае мы явно пишем, что это JSON
    xhr.setRequestHeader("Content-Type", "application/json");
    // когда придёт ответ на наше обращение к серверу, мы его обработаем здесь
    xhr.onreadystatechange = function () {
      // если запрос принят и сервер ответил, что всё в порядке
      if (xhr.readyState === 4 && xhr.status === 200) {
        // выводим то, что ответил нам сервер — так мы убедимся, что данные он получил правильно
        result.innerHTML = this.responseText;
      }
    };
    // преобразуем наши данные JSON в строку
    var data = JSON.stringify({ "name": name.value, "lastname": lastname.value });
    // когда всё готово, отправляем JSON на сервер
    xhr.send(data);
  }
</script>

Пишем PHP-скрипт для сервера

Зада­ча скрип­та пока будет очень про­стой — ему нуж­но будет полу­чить наши дан­ные и пока­зать, что всё при­шло как нуж­но. В PHP уже встро­е­на коман­да, кото­рая раз­би­ра­ет JSON-строку на состав­ля­ю­щие, поэто­му весь скрипт будет зани­мать три строч­ки:

<?php
// на какие данные рассчитан этот скрипт
header("Content-Type: application/json");
// разбираем JSON-строку на составляющие встроенной командой
$data = json_decode(file_get_contents("php://input"));
// отправляем в ответ строку с подтверждением
echo "Сервер получил следующие данные: имя — $data->name, фамилия — $data->lastname";

Для полу­че­ния дан­ных наш PHP-скрипт исполь­зу­ет стан­дарт­ную коман­ду file_get_contents("php://input"). Она про­сто ждёт, когда что-то при­ле­тит, и отправ­ля­ет резуль­тат в выбран­ную пере­мен­ную. Даль­ше её мож­но разо­брать как JSON-объект коман­дой json_decode() и рабо­тать с дан­ны­ми напря­мую.

Послед­няя коман­да echo отправ­ля­ет в ответ то, что напи­са­но в двой­ных кавыч­ках. Там мы обра­ща­ем­ся к пере­мен­ной $data, где хра­нят­ся при­слан­ные дан­ные. Имен­но этот ответ будет обра­ба­ты­вать скрипт на JavaScript, в функ­ции xhr.onreadystatechange, кото­рую мы про­пи­са­ли рань­ше.

Сам код нам нуж­но сохра­нить как json.php и поло­жить в пап­ку /projects/json/ на нашем сай­те — так мы про­пи­са­ли в скрип­те на JavaScript.

Настраиваем сервер

Если мы сей­час попро­бу­ем нажать на кноп­ку, бра­у­зер нам выдаст ошиб­ку:

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

Что­бы бра­у­зер раз­ре­шил нам полу­чать и отправ­лять дан­ные с сер­ве­ра, нам нуж­но настро­ить сер­вер. Настрой­ка про­ис­хо­дит в фай­ле .htaccess: это такой систем­ный файл, кото­рый лежит на вашем сер­ве­ре и под­ска­зы­ва­ет сер­ве­ру, как себя вести в раз­ных ситу­а­ци­ях, что-то вро­де инструк­ции. Назва­ние .htaccess неслу­чай­но: у фай­ла как бы нет име­ни, но есть рас­ши­ре­ние .htaccess, и в обыч­ных пап­ках этот файл не будет виден.

Созда­ём пустой файл, пишем в него вот такое кол­дов­ство и сохра­ня­ем как .htaccess

Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT" Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"

Пер­вая стро­ка раз­ре­ша­ет сер­ве­ру рабо­тать с запро­са­ми от любых стра­ниц (хоть это и небез­опас­но, но пока мы учим­ся — так мож­но). Вто­рая стро­ка содер­жит спи­сок раз­ре­шён­ных запро­сов. Тре­тья раз­ре­ша­ет нуж­ные нам заго­лов­ки в запро­се.

Фак­ти­че­ски этот файл сей­час озна­ча­ет: «раз­ре­шаю тебе при­ни­мать запро­сы со всех сай­тов, вот тако­го типа запро­сы мож­но при­ни­мать, вот такие у них могут быть заго­лов­ки». В бук­валь­ном смыс­ле мето­дич­ка.

Отку­да вы зна­е­те, что нуж­ны имен­но эти коман­ды?

Когда мы писа­ли эту ста­тью, нам потре­бо­ва­лось почи­тать спра­воч­ни­ки и фору­мы, про­те­сти­ро­вать несколь­ко вари­ан­тов команд и в ито­ге най­ти имен­но эту — ту, что рабо­та­ет.

Вся инфор­ма­ция по коман­дам и настрой­ке в интер­не­те уже есть. Нуж­но про­сто ее искать, ана­ли­зи­ро­вать и тести­ро­вать.

Теперь в интер­не­те есть ещё и эта ста­тья, кото­рая помо­жет вам мень­ше искать 🙂

Файл .htaccess нуж­но не поте­рять (на неко­то­рых опе­ра­ци­он­ках он ста­нет неви­ди­мым, как толь­ко вы его сохра­ни­те как .htaccess — при­дёт­ся поко­пать­ся в настрой­ках, что­бы его рас­крыть). Загру­жа­ем его на сер­вер.

Пере­за­пус­ка­ем нашу локаль­ную стра­нич­ку и про­бу­ем её в дей­ствии.

Всё рабо­та­ет. Синий текст мы полу­чи­ли от PHP-скрипта на сер­ве­ре. Связь нала­же­на!

Что дальше

Мы научи­лись отправ­лять дан­ные на сер­вер и немно­го рабо­тать там с ними. Даль­ше попро­бу­ем заме­нить в наших про­ек­тах локаль­ное хра­не­ние дан­ных на хра­не­ние на сер­ве­ре, что­бы про­ек­ты рабо­та­ли с любо­го бра­у­зе­ра.