Axios: JavaScript knihovna pro HTTP komunikaci

31.10.2020
Článek popisuje, jak používat knihovnu Axios pro komunikaci s webovým API. Jedná se o požadavky typu AJAX. Tato technika umožňuje JavaScriptu běžícímu v prohlížeči komunikovat s backend serverem na pozadí stránky. Axios využijeme také v Jest testech pro ověření správné funkčnosti.

Slovníček

ASP.NET Core Open-source webový framework od Microsoftu, poprvé vydaný v roce 2016.
Axios JavaScriptový HTTP/HTTPS klient.
Jest Testovací JavaScript framework od společnosti Facebook.
AJAX Způsob JavaScript komunikace mezi prohlížečem a webovým serverem.
Node.js Open-source, multiplatformní JavaScript runtime.
Npm Node package manager je správce balíčků v Node.js.
Babel Nástroj pro kompilaci a transpilaci JavaScriptu do konkrétních verzí pro zajištění kompatibility.

Obsah

Základní použití

Poslání GET požadavku
axios.get(url, config)
Poslání POST požadavku
axios.post(url, data, config)
Zpracování odpovědi
.then(function (response) { console.log(response) })
Error handling
.catch(function (error) {
  if (error.response) {
    // Request made and server responded
    console.log(error.response);
  } else if (error.request) {
    // The request was made but no response was received
    console.log(error.request);
  } else {
    // Something happened in setting up the request that triggered an Error
    console.log(error.message);
  }

Příprava backendu

Backend je velmi jednoduchý Controller v ASP.NET Core MVC aplikaci. Obsahuje dvě akce pro zpracování GET požadavku a dvě akce pro zpracování POST požadavku. Jedna akce je vždy bez úprav a druhá s použitím routy.
using Microsoft.AspNetCore.Mvc;

namespace WebApi.Controllers
{
    public class ApiController : Controller
    {
        [HttpGet]
        public IActionResult GetCommand(int? id)
        {
            if (id == null) return BadRequest();

            return Ok();
        }

        [HttpGet]
        [Route("api/getCommand/{id?}")]
        public IActionResult GetCommand2(int? id)
        {
            if (id == null) return BadRequest();

            return Ok();
        }

        [HttpPost]
        public IActionResult PostCommand(int? id)
        {
            if (id == null) return BadRequest();

            return Ok();
        }

        [HttpPost]
        [Route("api/postCommand/{id?}")]
        public IActionResult PostCommand2(int? id)
        {
            if (id == null) return BadRequest();

            return Ok();
        }
    }
}

Otestování pomocí frameworku Jest

Instalace

Pro instalaci použijeme baličkovací nástroj npm. V rootu našeho projektu vytvoříme konfigurační soubor package.json. Ten můžeme vytvořit buď
  • ručně
  • pomocí příkazu npm init
  • nebo přidat pomocí Visual Studia (Solution Explorer: Project Name > Add > New Item... > npm Configuration File)
V každém případě musí soubor obsahovat minimálně pole name a version. V příkazové řádce se přepneme do rootu našeho projektu a nainstalujeme framework. Příznak --save-dev říká, že nám Jest stačí ve vývojovém prostředí.
npm install --save-dev jest
Balíček a jeho závislosti se stáhli do složky node_modules, která se, pokud neexistuje, nově vytvoří. konfigurační soubor nyní může vypadat následovně
{
  "version": "1.0.0",
  "name": "asp.net",
  "private": true,
  "devDependencies": {
    "jest": "^26.6.1"
  }
}
dáme ještě konfiguračnímu souboru vědět, který framework pro testování použít
"scripts": {
  "test": "jest"
}
Protože budeme chtít v testovácím scriptu použít knihovnu axios, musíme jí nainstalovat pomocí npm, abychom jí mohli naimportovat jako modul.
npm install --save-dev axios
Jest používá pro transpilaci node balíčků transpilátor babel, který nainstalujeme a nakonfigurujeme.
npm install --save-dev babel-core
npm install --save-dev babel-preset-env
babel.config.js
module.exports = {
  presets: [['babel-preset-env', { targets: { node: 'current' } }]],
};
Dále budeme potřebovat balíčky https a qs
npm install --save-dev https
npm install --save-dev qs

Příprava GET testů

get.test.js
/**
* @jest-environment node
*/

import axios from 'axios';
import https from 'https';

const url = 'localhost:44370'
const agent = new https.Agent({ rejectUnauthorized: false });

test('GET request, ID in query parameter.', () => {

  expect.assertions(1);

  return axios.get(`https://${url}/api/getCommand?id=1`, { httpsAgent: agent })
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});

test('GET request, ID in params property.', () => {

  expect.assertions(1);

  return axios.get(`https://${url}/api/getCommand`, { httpsAgent: agent, params: { id: 1 } })
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});

test('GET request, ID as part of URL route.', () => {

  expect.assertions(1);

  return axios.get(`https://${url}/api/getCommand/1`, { httpsAgent: agent })
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});
  • @jest-environment node dáváme Jestu vědět, že se má spouštět pod node prostředím, jinak se použije javascriptový emulátor prohlížeče Jsdom, který by nám začal vracet chybové hlášky týkající se CORS pravidel.
  • nastavením https.Agent({ rejectUnauthorized: false }) říkáme, aby axios neověřoval self-signed certifikát u certifikačních autorit.

Příprava POST testů

post.test.js
/**
* @jest-environment node
*/

import axios from 'axios';
import https from 'https';
import qs from 'qs';

const url = 'localhost:44370'

test('POST request, ID in query parameter.', () => {

  expect.assertions(1);

  https.globalAgent.options.rejectUnauthorized = false;

  return axios.post(`https://${url}/api/postCommand?id=1`)
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});

test('POST request, ID is in data object.', () => {

  expect.assertions(1);

  https.globalAgent.options.rejectUnauthorized = false;

  const data = { id: 1 }

  return axios.post(`https://${url}/api/postCommand`, qs.stringify(data))
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});

test('POST request, ID as part of URL route.', () => {

  expect.assertions(1);

  https.globalAgent.options.rejectUnauthorized = false;

  return axios.post(`https://${url}/api/postCommand/1`)
      .then(function (response) {
          expect(response.status).toBe(200);
      })
});'
  • https.globalAgent.options.rejectUnauthorized = false; dělá to samé co https.Agent({ rejectUnauthorized: false }) ale funguje i pro POST požadavek. Agent třída mi pro POST požadavek nefungovala.
  • qs.stringify převede parametry na JSON objekt.

Spuštění

npm test -- --verbose

Odkazy