Skip to content

Tinkoff/mockingbird

Repository files navigation

mockingbird

mockingbird - сСрвис эмуляции REST-сСрвисов ΠΈ сСрвисов с интСрфСйсами-очСрСдями

Руководство ΠΏΠΎ инсталляции

Руководство ΠΏΠΎ настройкС

Π Π°Π±ΠΎΡ‚Π° с очСрСдями

ΠžΠ±Ρ‰ΠΈΠ΅ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹

mockingbird ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ сцСнарии:

  • ΠΏΡ€ΠΎΠ³ΠΎΠ½ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ кСйса с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ Π½Π°Π±ΠΎΡ€ΠΎΠΌ событий ΠΈ HTTP/GRPC ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ²
  • постоянная имитация happy-path для обСспСчСния автономности ΠΊΠΎΠ½Ρ‚ΡƒΡ€Π°(ΠΎΠ²)

Π’ΠΈΠΏΡ‹ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΉ:

  • countdown - Π°Π²Ρ‚ΠΎΠ½ΠΎΠΌΠ½Ρ‹Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ для тСстирования ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ сцСнария. Π˜ΠΌΠ΅ΡŽΡ‚ Π½Π°ΠΈΠ²Ρ‹ΡΡˆΠΈΠΉ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ ΠΏΡ€ΠΈ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΈ нСоднозначностСй. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΌΠΎΠΊ срабатываСт n Ρ€Π°Π· (количСство задаётся ΠΏΡ€ΠΈ создании). АвтоматичСски ΡƒΠ΄Π°Π»ΡΡŽΡ‚ΡΡ Π² ΠΏΠΎΠ»Π½ΠΎΡ‡ΡŒ.
  • ephemeral - ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ, автоматичСски удаляСмыС Π² ΠΏΠΎΠ»Π½ΠΎΡ‡ΡŒ. Если ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄/ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ сообщСниС, для ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚ countdown ΠΈ ephemeral ΠΌΠΎΠΊΠΈ - сработаСт countdown.
  • persistent - конфигурация, прСдназначСная для постоянной Ρ€Π°Π±ΠΎΡ‚Ρ‹. Π˜ΠΌΠ΅Π΅Ρ‚ наимСньший ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ нСбольшого кСйса (короткая заявка) - Π² ΠΊΠΎΠ½Ρ†Π΅ спСцификации

БСрвисы

Для упорядочСния ΠΌΠΎΠΊΠΎΠ² Π² UI ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ количСства ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚Π½Ρ‹Ρ… ситуаций Π² mockingbird Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹ Ρ‚.Π½. сСрвисы. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΌΠΎΠΊ (ΠΊΠ°ΠΊ HTTP Ρ‚Π°ΠΊ ΠΈ сцСнарий) всСгда ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ‚ ΠΊ ΠΊΠ°ΠΊΠΎΠΌΡƒ-Ρ‚ΠΎ ΠΈΠ· сСрвисом. БСрвисы ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ Π·Π°Ρ€Π°Π½Π΅Π΅ ΠΈ хранятся Π² Π±Π°Π·Π΅. БСрвис ΠΈΠΌΠ΅Π΅Ρ‚ suffix (ΡΠ²Π»ΡΡŽΡ‰ΠΈΠΉΡΡ ΠΏΠΎ ΡΠΎΠ²ΠΌΠ΅ΡΡ‚ΠΈΡ‚Π΅Π»ΡŒΡΡ‚Π²Ρƒ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌ id сСрвиса) ΠΈ Ρ‡Π΅Π»ΠΎΠ²Π΅ΠΊΠΎΡ‡ΠΈΡ‚Π°Π΅ΠΌΡ‹ΠΉ name.

Π¨Π°Π±Π»ΠΎΠ½ΠΈΠ·Π°Ρ‚ΠΎΡ€ JSON

Для достиТСния гибкости ΠΏΡ€ΠΈ сохранСнии ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ простоты ΠΊΠΎΠ½Ρ„ΠΈΠ³ΠΎΠ² Π² сСрвисС Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ JSON ΡˆΠ°Π±Π»ΠΎΠ½ΠΈΠ·Π°Ρ‚ΠΎΡ€. Для Π½Π°Ρ‡Π°Π»Π° простой ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

Π¨Π°Π±Π»ΠΎΠ½:

{
  "description": "${description}",
  "topic": "${extras.topic}",
  "comment": "${extras.comments.[0].text}",
  "meta": {
    "field1": "${extras.fields.[0]}"
  }
}

ЗначСния для подстановки:

{
  "description": "Some description",
  "extras": {
    "fields": ["f1", "f2"],
    "topic": "Main topic",
    "comments": [
      {"text": "First nah!"}, {"text": "Okay"}
    ]
  }
}

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚:

{
  "description": "Some description",
  "topic": "Main topic",
  "comment": "First nah!",
  "meta": {
    "field1": "f1"
  }
}

Π’ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ поддСрТиваСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ синтаксис:

  • ${a.[0].b} - подстановка значСния (JSON)
  • ${/a/b/c} - подстановка значСния (XPath)

Π’ΠΠ˜ΠœΠΠΠ˜Π•! НЕ Π˜Π‘ΠŸΠžΠ›Π¬Π—Π£Π™Π’Π• ΠΠ•Π™ΠœΠ‘ΠŸΠ•Π™Π‘Π« Π’ XPATH Π’Π«Π ΠΠ–Π•ΠΠ˜Π―Π₯

Π¨Π°Π±Π»ΠΎΠ½ΠΈΠ·Π°Ρ‚ΠΎΡ€ XML

Π¨Π°Π±Π»ΠΎΠ½:

<root>
    <tag1>${/r/t1}</tag1>
    <tag2 a2="${/r/t2/@a2}">${/r/t2}</tag2>
</root>

ЗначСния для подстановки:

<r>
    <t1>test</t1>
    <t2 a2="attr2">42</t2>
</r>

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚:

<root>
    <tag1>test</tag1>
    <tag2 a2="attr2">42</tag2>
</root>

Бостояния (state)

Для ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ слоТных сцСнариСв сСрвис ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ сохранСниС ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹Ρ… состояний. БостояниС - Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½ΠΎΠΉ схСмой, тСхничСски состояниС - Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ Π² mongodb. Π—Π°ΠΏΠΈΡΡŒ Π½ΠΎΠ²Ρ‹Ρ… состояний ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΎΠΈΡΡ…ΠΎΠ΄ΠΈΡ‚ΡŒ:

  • ΠΏΡ€ΠΈ записи Π² state (сСкция persist) с пустым (ΠΈΠ»ΠΈ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ) ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚ΠΎΠΌ (сСкция state)

ΠœΠ°Π½ΠΈΠΏΡƒΠ»ΡΡ†ΠΈΠΈ со state

State аккумулятивно дописываСтся. Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ пСрСписываниС ΠΏΠΎΠ»Π΅ΠΉ.

Поля, ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Π±ΡƒΠ΄Π΅ΠΌ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ поиск (ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π² ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Π°Ρ…) Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π½Π°Ρ‡ΠΈΠ½Π°Ρ‚ΡŒΡΡ с "_".

для Ρ‚Π°ΠΊΠΈΡ… ΠΏΠΎΠ»Π΅ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ автоматичСски ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒΡΡ sparse индСкс

ΠŸΡ€Π΅Ρ„ΠΈΠΊΡΡ‹:

  • seed - значСния ΠΈΠ· Π±Π»ΠΎΠΊΠ° seed (Ρ€Π°Π½Π΄ΠΎΠΌΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Π΅ Π½Π° стартС заявки)
  • state - Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ state
  • req - Ρ‚Π΅Π»ΠΎ запроса (Ρ€Π΅ΠΆΠΈΠΌΡ‹ json, jlens, xpath)
  • message - Ρ‚Π΅Π»ΠΎ собщСния (Π² сцСнариях)
  • query - query ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ (Π² Π·Π°Π³Π»ΡƒΡˆΠΊΠ°Ρ…)
  • pathParts - значСния, ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌΡ‹Π΅ ΠΈΠ· URL (Π² Π·Π°Π³Π»ΡƒΡˆΠΊΠ°Ρ…) см. Экстрация Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· URL
  • extracted - ΠΈΠ·Π²Π»Π΅Ρ‡Ρ‘Π½Π½Ρ‹Π΅ значСния
  • headers - HTTP Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ
{
  "a": "ΠŸΡ€ΠΎΡΡ‚ΠΎ строка", //Π’ ΠΏΠΎΠ»Π΅ "a" записываСтся константа (ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ любоС JSON Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅)
  "b": "${req.fieldB}", //Π’ ΠΏΠΎΠ»Π΅ "b" записываСтся Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΠ· поля fieldB запроса
  "c": "${state.c}", //Π’ ΠΏΠΎΠ»Π΅ "c" записываСтся Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΠ· поля "c" Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π³ΠΎ состояния
  "d": "${req.fieldA}: ${state.a}" //Π’ ΠΏΠΎΠ»Π΅ d Π·Π°ΠΏΠΈΡˆΠ΅Ρ‚ΡΡ строка, содСрТащая req.fieldA ΠΈ state.a
}

Поиск state

ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹ для поиска state ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡΠ»ΡΡŽΡ‚ΡΡ Π² Π±Π»ΠΎΠΊΠ΅ state. ΠŸΡƒΡΡ‚ΠΎΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ({}) Π² ΠΏΠΎΠ»Π΅ state нСдопустим. Для поиска state ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ запроса (Π±Π΅Π· прСфикса), query ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ (прСфикс __query), значСния, ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌΡ‹Π΅ ΠΈΠ· URL (прСфикс __segments) ΠΈ HTTP Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ (прСфикс __headers)

ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

{
  "_a": "${fieldB}", //ΠΏΠΎΠ»Π΅ ΠΈΠ· Ρ‚Π΅Π»Π° запроса
  "_b": "${__query.arg1}", //query ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€
  "_c": "${__segments.id}", //сСгмСнт URL, см. `Экстрация Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· URL`
  "_d": "${__headers.Accept}" //HTTP Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ
}

Seeding

Иногда Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ ΡΠ³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ случайноС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΈ/ΠΈΠ»ΠΈ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Π΅Π³ΠΎ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΌΠΎΠΊΠ°. Для ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ Ρ‚Π°ΠΊΠΈΡ… сцСнариСв сдСлано ΠΏΠΎΠ»Π΅ seed, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰Π΅Π΅ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ сгСнСрированы ΠΏΡ€ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΊΠ°. Π­Ρ‚ΠΎ позволяСт ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ нСобходимости ΠΏΠ΅Ρ€Π΅ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΌΠΎΠΊΠΈ с Π·Π°Ρ…Π°Ρ€Π΄ΠΊΠΎΠΆΠ΅Π½Ρ‹ΠΌΠΈ id

Π’ seed'Π°Ρ… поддСрТиваСтся синтаксис псСвдофункций:

  • %{randomString(n)} - подстановка случайной строки Π΄Π»ΠΈΠ½ΠΎΠΉ n
  • %{randomString("ABCDEF1234567890", m, n)} - подстановка случайной строки, состоящСй ΠΈΠ· символов ABCDEF1234567890 Π΄Π»ΠΈΠ½ΠΎΠΉ Π² ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»Π΅ [m, n)
  • %{randomNumericString(n)} - подстановка случайной строки, состоящСй Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ· Ρ†ΠΈΡ„Ρ€, Π΄Π»ΠΈΠ½ΠΎΠΉ n
  • %{randomInt(n)} - подстановка случайного Int Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅ [0, n)
  • %{randomInt(m,n)} - подстановка случайного Int Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅ [m, n)
  • %{randomLong(n)} - подстановка случайного Long Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅ [0, n)
  • %{randomLong(m,n)} - подстановка случайного Long Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅ [m, n)
  • %{UUID} - подстановка случайного UUID
  • %{now(yyyy-MM-dd'T'HH:mm:ss)} - Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ врСмя Π² Π·Π°Π΄Π°Π½Π½ΠΎΠΌ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅
  • %{today(yyyy-MM-dd)} - тСкущая Π΄Π°Ρ‚Π° Π² Π·Π°Π΄Π°Π½Π½ΠΎΠΌ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅

МоТно ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ строки со слоТным Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠΌ: %{randomInt(10)}: %{randomLong(10)} | %{randomString(12)}, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ всС псСвдофункции ΠΈΠ· списка Π²Ρ‹ΡˆΠ΅

Π Π΅Π·ΠΎΠ»Π²ΠΈΠ½Π³ Π·Π°Π³Π»ΡƒΡˆΠ΅ΠΊ/сцСнариСв

НайдСныС Π·Π°Π³Π»ΡƒΡˆΠΊΠΈ - ΠΊΠ°Π½Π΄ΠΈΠ΄Π°Ρ‚Ρ‹, ΠΎΡΡ‚Π°Π²ΡˆΠΈΠ΅ΡΡ послС Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ URL, Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² ΠΈ Ρ‚Π΅Π»Π° запроса НайдСныС сцСнарии - ΠΊΠ°Π½Π΄ΠΈΠ΄Π°Ρ‚Ρ‹, ΠΎΡΡ‚Π°Π²ΡˆΠΈΠ΅ΡΡ послС Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ Ρ‚Π΅Π»Π° сообщСния

НайдСныС Π·Π°Π³Π»ΡƒΡˆΠΊΠΈ (сцСнарии) ВрСбуСтся состояниС НайдСно состояний Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚
β„–1 Π½Π΅Ρ‚ - Π‘Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ β„–1
β„–1 Π΄Π° 0 Ошибка
β„–1 Π΄Π° 1 Π‘Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ β„–1
β„–1
β„–2
Π½Π΅Ρ‚
Π½Π΅Ρ‚
- Ошибка
β„–1
β„–2
Π½Π΅Ρ‚
Π΄Π°
-
0
Π‘Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ β„–1
β„–1
β„–2
Π½Π΅Ρ‚
Π΄Π°
-
1
Π‘Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ β„–2
β„–1
β„–2
Π½Π΅Ρ‚
Π΄Π°
-
2 (ΠΈ Π±ΠΎΠ»Π΅Π΅)
Ошибка
β„–1
β„–2
Π΄Π°
Π΄Π°
0
0
Ошибка
β„–1
β„–2
Π΄Π°
Π΄Π°
0
1
Π‘Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ β„–2
β„–1
β„–2
Π΄Π°
Π΄Π°
0
2 (ΠΈ Π±ΠΎΠ»Π΅Π΅)
Ошибка
β„–1
β„–2
Π΄Π°
Π΄Π°
1
1 (ΠΈ Π±ΠΎΠ»Π΅Π΅)
Ошибка
β„–1
β„–2
β„–3
Π΄Π°
Π΄Π°
Π΄Π°
0
1
0
Π‘Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ β„–2
β„–1
β„–2
β„–3
Π΄Π°
Π΄Π°
Π΄Π°
0
1
1
Ошибка
β„–1
β„–2
β„–3
Π΄Π°
Π΄Π°
Π΄Π°
0
2
0
Ошибка

Эмуляция REST сСрвисов

Алгоритм Ρ€Π°Π±ΠΎΡ‚Ρ‹:

  1. Поиск мока по URL/HTTP-verb/заголовков
  2. Валидация body
  3. Поиск state ΠΏΠΎ ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρƒ
  4. ΠŸΠΎΠ΄ΡΡ‚Π°Π½ΠΎΠ²ΠΊΠ° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π² шаблон ΠΎΡ‚Π²Π΅Ρ‚Π°
  5. ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡ state
  6. ΠžΡ‚Π΄Π°Ρ‡Π° response

ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ HTTP Π·Π°Π³Π»ΡƒΡˆΠ΅ΠΊ

HTTP Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ Π²Π°Π»ΠΈΠ΄ΠΈΡ€ΡƒΡŽΡ‚ΡΡ Π½Π° ΠΏΠΎΠ»Π½ΠΎΠ΅ соотвСтствиС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, лишниС Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ ошибкой

Валидация Ρ‚Π΅Π»Π° запросы Π² HTTP Π·Π°Π³Π»ΡƒΡˆΠΊΠ°Ρ… ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… Ρ€Π΅ΠΆΠΈΠΌΠ°Ρ…:

  • no_body - запрос Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Π±Π΅Π· Ρ‚Π΅Π»Π°
  • any_body - Ρ‚Π΅Π»ΠΎ запроса Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π½Π΅ пустым, ΠΏΡ€ΠΈ этом Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ парсится ΠΈ Π½Π΅ провСряСтся
  • raw - Ρ‚Π΅Π»ΠΎ запроса Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ парсится ΠΈ провСряСтся Π½Π° ΠΏΠΎΠ»Π½ΠΎΠ΅ соотвСтствиС с содСрТимым request.body
  • json - Ρ‚Π΅Π»ΠΎ запроса Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π²Π°Π»ΠΈΠ΄Π½Ρ‹ΠΌ JSON'ΠΎΠΌ ΠΈ провСряСтся Π½Π° соотвСтствиС с содСрТимым request.body
  • xml - Ρ‚Π΅Π»ΠΎ запроса Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π²Π°Π»ΠΈΠ΄Π½Ρ‹ΠΌ XML ΠΈ провСряСтся Π½Π° соотвСтствиС с содСрТимым request.body
  • jlens - Ρ‚Π΅Π»ΠΎ запроса Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π²Π°Π»ΠΈΠ΄Π½Ρ‹ΠΌ JSON'ΠΎΠΌ ΠΈ валидируСтся ΠΏΠΎ условиям, описаным Π² request.body
  • xpath - Ρ‚Π΅Π»ΠΎ запроса Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π²Π°Π»ΠΈΠ΄Π½Ρ‹ΠΌ XML ΠΈ валидируСтся ΠΏΠΎ условиям, описаным Π² request.body
  • web_form - Ρ‚Π΅Π»ΠΎ запроса Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ x-www-form-urlencoded ΠΈ валидируСтся ΠΏΠΎ условиям, описаным Π² request.body
  • multipart - Ρ‚Π΅Π»ΠΎ запроса Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ multipart/form-data. ΠŸΡ€Π°Π²ΠΈΠ»Π° Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ частСй ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΡƒΡŽΡ‚ΡΡ ΠΈΠ½Π΄ΠΈΠ²ΠΈΠ΄ΡƒΠ°Π»ΡŒΠ½ΠΎ (см. Ρ€Π°Π·Π΄Π΅Π» Π½ΠΈΠΆΠ΅)

Π’ΠΠ˜ΠœΠΠΠ˜Π•! multipart запросы Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π½Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ - /api/mockingbird/execmp

Для ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ² ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ Ρ€Π΅ΠΆΠΈΠΌΡ‹:

  • raw
  • json
  • xml
  • binary
  • proxy
  • json-proxy
  • xml-proxy

Π Π΅ΠΆΠΈΠΌΡ‹ request ΠΈ response ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ нСзависимы Π΄Ρ€ΡƒΠ³ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³Π° (ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π²Π΅Ρ‚ xml'Π΅ΠΌ Π½Π° json запрос ΠΏΡ€ΠΈ ΠΆΠ΅Π»Π°Π½ΠΈΠΈ, ΠΊΡ€ΠΎΠΌΠ΅ Ρ€Π΅ΠΆΠΈΠΌΠΎΠ² json-proxy ΠΈ xml-proxy)

Π’ ΠΏΠΎΠ»Π΅ delay ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹ΠΉ FiniteDuration Π½Π΅ дольшС 30 сСкунд

Экстрация Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· URL

Π‘Ρ‹Π²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ URL содСрТит ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Π½Π΅ ΠΊΠ°ΠΊ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€, Π° ΠΊΠ°ΠΊ нСпосрСдствСнно Ρ‡Π°ΡΡ‚ΡŒ ΠΏΡƒΡ‚ΠΈ. Π’ Ρ‚Π°ΠΊΠΈΡ… случаях становится Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹ΠΌ ΠΎΠΏΠΈΡΠ°Ρ‚ΡŒ persistent Π·Π°Π³Π»ΡƒΡˆΠΊΡƒ ΠΈΠ·-Π·Π° нСвозмоТности ΠΏΠΎΠ»Π½ΠΎΠ³ΠΎ совпадСния ΠΏΡƒΡ‚ΠΈ. На ΠΏΠΎΠΌΠΎΡ‰ΡŒ ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ ΠΏΠΎΠ»Π΅ pathPattern, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ рСгулярку, Π½Π° соотвСтствиС ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒΡΡ ΠΏΡƒΡ‚ΡŒ. ΠžΡ‚ΠΌΠ΅Ρ‡Ρƒ, Ρ‡Ρ‚ΠΎ Ρ…ΠΎΡ‚ΡŒ сопоставлСниС ΠΈ производится Π² ΠΌΠΎΠ½Π³Π΅ эффСктивным способом, Π·Π»ΠΎΡƒΠΏΠΎΡ‚Ρ€Π΅Π±ΡΡ‚ΡŒ этой Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ Π½Π΅ стоит ΠΈ ΠΏΡ€ΠΈ возмоТности сопоставлСния ΠΏΠΎ ΠΏΠΎΠ»Π½ΠΎΠΌΡƒ совпадСнию Π½Π΅ слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ pathPattern

ΠŸΡ€ΠΈΠΌΠ΅Ρ€:

{
  "name": "Sample stub",
  "scope": "persistent",
  "pathPattern": "/pattern/(?<id>\d+)",
  "method": "GET",
  "request": {
    "headers": {},
    "mode": "no_body",
    "body": {}
  },
  "response": {
    "code": 200,
    "mode": "json",
    "headers": {"Content-Type":  "application/json"},
    "body": {"id": "${pathParts.id}"}
  }
}

Π’ΠΎ, Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ·Π²Π»Π΅Ρ‡ΡŒ ΠΈΠ· ΠΏΡƒΡ‚ΠΈ, Π½ΡƒΠΆΠ½ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΎΠΉ Π³Ρ€ΡƒΠΏΠΏΠΎΠΉ, Π³Ρ€ΡƒΠΏΠΏ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ сколько ΡƒΠ³ΠΎΠ΄Π½ΠΎ, впослСдствии Π½Π° Π½ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ Ρ‡Π΅Ρ€Π΅Π· pathParts.<имя_Π³Ρ€ΡƒΠΏΠΏΡ‹>

Экстракторы

Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… случаях Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΠ΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π² ΠΎΡ‚Π²Π΅Ρ‚ Π΄Π°Π½Π½Ρ‹Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·Π²Π»Π΅Ρ‡ΡŒ простыми срСдствами. Для этих Ρ†Π΅Π»Π΅ΠΉ Π±Ρ‹Π»ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ экстракторы

Экстрактор xcdata

Достаёт значСния ΠΈΠ· XML, Π»Π΅ΠΆΠ°Ρ‰Π΅Π³ΠΎ Π² CDATA

конфигурация:

{
  "type": "xcdata",
  "prefix": "/root/inner/tag", //ΠŸΡƒΡ‚ΡŒ Π΄ΠΎ тэга с CDATA
  "path": "/path/to" //ΠŸΡƒΡ‚ΡŒ Π΄ΠΎ Π½ΡƒΠΆΠ½ΠΎΠ³ΠΎ тэга
}

Экстрактор jcdata

Достаёт значСния ΠΈΠ· JSON, Π»Π΅ΠΆΠ°Ρ‰Π΅Π³ΠΎ Π² CDATA

конфигурация:

{
  "type": "jcdata",
  "prefix": "/root/inner/tag", //ΠŸΡƒΡ‚ΡŒ Π΄ΠΎ тэга с CDATA
  "path": "path.to" //ΠŸΡƒΡ‚ΡŒ Π΄ΠΎ Π½ΡƒΠΆΠ½ΠΎΠ³ΠΎ значСния
}

CDATA inlining

Иногда приходится ΠΈΠΌΠ΅Ρ‚ΡŒ Π΄Π΅Π»ΠΎ с запросами, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π²Π½ΡƒΡ‚Ρ€ΠΈ CDATA Π»Π΅ΠΆΠΈΡ‚ XML. Π’ Ρ‚Π°ΠΊΠΈΡ… случаях ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΈΠ½Π»Π°ΠΉΠ½ΠΈΡ‚ΡŒ содСрТимоС DATA с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° inlineCData (поддСрТиваСтся Π² xpath ΠΈ xml)

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹

ПолноС совпадСниС, Ρ€Π΅ΠΆΠΈΠΌ json

{
    "name": "Sample stub",
    "method": "POST",
    "path": "/pos-loans/api/cl/get_partner_lead_info",
    "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
    },
    "request": {
        "headers": {"Content-Type": "application/json"},
        "mode": "json",
        "body": {
            "trace_id": "42",
            "account_number": "228"
        }
    },
    "persist": {
      // ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ состояния
    },
    "response": {
        "code": 200,
        "mode": "json",
        "body": {
            "code": 0,
            "credit_amount": 802400,
            "credit_term": 120,
            "interest_rate": 13.9,
            "partnum": "CL3.15"
        },
        "headers": {"Content-Type": "application/json"},
        "delay": "1 second"
    }
}

ПолноС совпадСниС, Ρ€Π΅ΠΆΠΈΠΌ raw

{
    "name": "Sample stub",
    "method": "POST",
    "path": "/pos-loans/api/evil/soap/service"
    "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
    },
    "request": {
        "headers": {"Content-Type": "application/xml"},
        "mode": "raw"
        "body": "<xml><request type=\"rqt\"></request></xml>"
    },
    "persist": {
      // ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ состояния
    },
    "response": {
        "code": 200,
        "mode": "raw"
        "body": "<xml><response type=\"rqt\"></response></xml>",
        "headers": {"Content-Type": "application/xml"},
        "delay": "1 second"
    }
}

Валидация ΠΏΠΎ условиям, Ρ€Π΅ΠΆΠΈΠΌ jlens

{
    "name": "Sample stub",
    "method": "POST",
    "path": "/pos-loans/api/cl/get_partner_lead_info",
    "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
    },
    "request": {
        "headers": {"Content-Type": "application/json"},
        "mode": "jlens",
        "body": {
            "meta.id": {"==": 42}
        }
    },
    "persist": {
      // ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ состояния
    },
    "response": {
        "code": 200,
        "mode": "json",
        "body": {
            "code": 0,
            "credit_amount": 802400,
            "credit_term": 120,
            "interest_rate": 13.9,
            "partnum": "CL3.15"
        },
        "headers": {"Content-Type": "application/json"},
        "delay": "1 second"
    }
}

Валидация ΠΏΠΎ условиям, Ρ€Π΅ΠΆΠΈΠΌ xpath

Π’ΠΠ˜ΠœΠΠΠ˜Π•! НЕ Π˜Π‘ΠŸΠžΠ›Π¬Π—Π£Π™Π’Π• ΠΠ•Π™ΠœΠ‘ΠŸΠ•Π™Π‘Π« Π’ XPATH Π’Π«Π ΠΠ–Π•ΠΠ˜Π―Π₯

{
    "name": "Sample stub",
    "method": "POST",
    "path": "/pos-loans/api/cl/get_partner_lead_info",
    "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
    },
    "request": {
        "headers": {"Content-Type": "application/xml"},
        "mode": "xpath",
        "body": {
            "/payload/response/id": {"==": 42}
        },
        "extractors": {"name": {...}, ...} //ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ
    },
    "persist": {
      // ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ состояния
    },
    "response": {
        "code": 200,
        "mode": "raw"
        "body": "<xml><response type=\"rst\"></response></xml>",
        "headers": {"Content-Type": "application/xml"},
        "delay": "1 second"
    }
}

Валидация ΠΏΠΎ условиям, Ρ€Π΅ΠΆΠΈΠΌ multipart

Π’ΠΠ˜ΠœΠΠΠ˜Π•! multipart запросы Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ Π½Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ - /api/mockingbird/execmp

Π Π΅ΠΆΠΈΠΌΡ‹ Π²Π°Π»ΠΈΠ΄Π°Π½ΠΈΠΈ part:

  • any - Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ валидируСтся
  • raw - ΠΏΠΎΠ»Π½ΠΎΠ΅ соотвСтствиС
  • json - ΠΏΠΎΠ»Π½ΠΎΠ΅ соотвСтствиС, Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ парсится ΠΊΠ°ΠΊ Json
  • xml - ΠΏΠΎΠ»Π½ΠΎΠ΅ соотвСтствиС, Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ парсится ΠΊΠ°ΠΊ XML
  • urlencoded - Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Ρ€Π΅ΠΆΠΈΠΌΡƒ web_form для Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ всСго Ρ‚Π΅Π»Π°
  • jlens - ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Json ΠΏΠΎ условиям
  • xpath - ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° XML ΠΏΠΎ условиям
{
    "name": "Sample stub",
    "method": "POST",
    "path": "/test/multipart",
    "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
    },
    "request": {
        "headers": {},
        "mode": "multipart",
        "body": {
            "part1": {
              "mode": "json", //Ρ€Π΅ΠΆΠΈΠΌ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ
              "headers": {}, //Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ part
              "value": {} //спСцификация значСния для Π²Π°Π»ΠΈΠ΄Π°Ρ‚ΠΎΡ€Π°
            },
            "part2": {
              ...
            }
        },
        "bypassUnknownParts": true //Ρ„Π»Π°Π³, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ всС partΡ‹, ΠΎΡ‚ΡΡƒΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ Π² спСцификации Π²Π°Π»ΠΈΠ΄Π°Ρ‚ΠΎΡ€Π°
                                   //ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Ρ„Π»Π°Π³ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½, ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ (false)
    },
    "persist": {
      // ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ состояния
    },
    "response": {
        "code": 200,
        "mode": "json",
        "body": {
            "code": 0,
            "credit_amount": 802400,
            "credit_term": 120,
            "interest_rate": 13.9,
            "partnum": "CL3.15"
        },
        "headers": {"Content-Type": "application/json"},
        "delay": "1 second"
    }
}

ΠŸΡ€ΠΎΡΡ‚ΠΎΠ΅ проксированиС запроса

{
  "name": "Simple proxy",
  "method": "POST",
  "path": "/pos-loans/api/cl/get_partner_lead_info",
  "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
  },
  "request": {
    // БпСцификация запроса
  },
  "response": {
    "mode": "proxy",
    "uri": "http://some.host/api/cl/get_partner_lead_info"
  }
}

ΠŸΡ€ΠΎΠΊΡΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ с ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠ΅ΠΉ JSON ΠΎΡ‚Π²Π΅Ρ‚Π°

{
  "name": "Simple proxy",
  "method": "POST",
  "path": "/pos-loans/api/cl/get_partner_lead_info",
  "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
  },
  "request": {
    // БпСцификация запроса, mode json ΠΈΠ»ΠΈ jlens
  },
  "response": {
    "mode": "json-proxy",
    "uri": "http://some.host/api/cl/get_partner_lead_info",
    "patch": {
      "field.innerField": "${req.someRequestField}"
    }
  }
}

ΠŸΡ€ΠΎΠΊΡΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ с ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠ΅ΠΉ XML ΠΎΡ‚Π²Π΅Ρ‚Π°

{
  "name": "Simple proxy",
  "method": "POST",
  "path": "/pos-loans/api/cl/get_partner_lead_info",
  "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
  },
  "request": {
    // БпСцификация запроса, mode xml ΠΈΠ»ΠΈ xpath
  },
  "response": {
    "mode": "xml-proxy",
    "uri": "http://some.host/api/cl/get_partner_lead_info",
    "patch": {
      "/env/someTag": "${/some/requestTag}"
    }
  }
}

DSL ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚ΠΎΠ² Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ JSON ΠΈ XML

Π² Ρ€Π΅ΠΆΠΈΠΌΠ°Ρ… jlens ΠΈ xpath поддСрТиваСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅:

{
  "a": {"==": "some value"}, //ΠΏΠΎΠ»Π½ΠΎΠ΅ соотвСтствиС
  "b": {"!=": "some value"}, //Π½Π΅ Ρ€Π°Π²Π½ΠΎ
  "c": {">": 42} | {">=": 42} | {"<": 42} | {"<=": 42}, //сравнСния, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для чисСл, ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΡƒΡŽΡ‚ΡΡ
  "d": {"~=": "\d+"}, //сопоставлСниС с regexp,
  "e": {"size": 10}, //Π΄Π»ΠΈΠ½Π°, для массивов ΠΈ строк
  "f": {"exists": true} //ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° сущСствования
}

ΠšΠ»ΡŽΡ‡Π°ΠΌΠΈ Π² Ρ‚Π°ΠΊΠΈΡ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°Ρ… являСтся Π»ΠΈΠ±ΠΎ ΠΏΡƒΡ‚ΡŒ Π² json ("a.b.[0].c") Π»ΠΈΠ±ΠΎ xpath ("/a/b/c") Π—Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: Π² Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ сравнСния ΠΌΠΎΠ³ΡƒΡ‚ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с xpath, ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΌΠΈ Π½Π° XML Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Ρ‹. ΠžΠ±ΠΎΠΉΡ‚ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ Π½Π° сущСствованиС/нСсущСствованиС: /tag/otherTag/[@attr='2']": {"exists": true}

Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ jlens Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ:

{
    "g": {"[_]": ["1", 2, true]}, //ΠΏΠΎΠ»Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΠΎΠ΄Π½ΠΎ ΠΈΠ· пСрСчислСных Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ
    "h": {"![_]": ["1", 2, true]}, //ΠΏΠΎΠ»Π΅ НЕ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ Π½ΠΈ ΠΎΠ΄Π½ΠΎ ΠΈΠ· пСрСчислСных Π·Π½Π°Π΅Ρ‡Π½ΠΈΠΉ
    "i": {"&[_]": ["1", 2, true]} // ΠΏΠΎΠ»Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ массивом ΠΈ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ всС пСрСчислСнныС значСния (ΠΏΡ€ΠΈ этом порядок Π½Π΅ Π²Π°ΠΆΠ΅Π½)
}

Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ xpath Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ:

  "/some/tag": {"cdata": {"==": "test"}}, //валидация Π½Π° ΠΏΠΎΠ»Π½ΠΎΠ΅ совпадСниС CDATA, Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Π‘Π’Π ΠžΠšΠžΠ™
  "/some/tag": {"cdata": {"~=": "\d+"}}, //валидация DATA рСгуляркой, Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Π‘Π’Π ΠžΠšΠžΠ™
  "/some/tag": {"jcdata": {"a": {"==": 42}}}, //Π²Π°Π»ΠΈΠ΄ΠΈΡ€ΡƒΠ΅ΠΌ содСрТимоС CDATA ΠΊΠ°ΠΊ JSON, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ всС доступныС ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
  "/other/tag": {"xcdata": {"/b": {"==": 42}}} //Π²Π°Π»ΠΈΠ΄ΠΈΡ€ΡƒΠ΅ΠΌ содСрТимоС CDATA ΠΊΠ°ΠΊ XML, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ всС доступныС ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹

Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ web_form ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Π’ΠžΠ›Π¬ΠšΠž ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ: ==, !=, ~=, size, [_], ![_], &[_]

Эмуляция GRPC сСрвисов

Как это устроСно ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡ‚ΠΎΠΌ: ΠŸΡ€ΠΈ создании ΠΌΠΎΠΊΠ° Π²Π»ΠΎΠΆΠ΅Π½Ρ‹Π΅ Π² запрос proto Ρ„Π°ΠΉΠ»Ρ‹ парсятся ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΡŽΡ‚ΡΡ Π² json-прСдставлСниС protobuf схСмы. Π’ Π±Π°Π·Π΅ хранится ΠΈΠΌΠ΅Π½Π½ΠΎ json-прСдставлСниС, Π° Π½Π΅ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ proto Ρ„Π°ΠΉΠ». ΠŸΠ΅Ρ€Π²ΠΎΠ΅ срабатываниС ΠΌΠΎΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π½ΠΈΠΌΠ°Ρ‚ΡŒ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ большС Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Ρ‡Π΅ΠΌ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅, Ρ‚.ΠΊ. ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ срабатывании ΠΈΠ· json-прСдставляСния гСнСрируСтся Π΄Π΅ΠΊΠΎΠ΄Π΅Ρ€ protobuf сообщСний. ПослС дСкодирования Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΡŽΡ‚ΡΡ Π² json, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ провСряСтся json-ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Π°ΠΌΠΈ, Π·Π°Π΄Π°Π½Ρ‹ΠΌΠΈ Π² ΠΏΠΎΠ»Π΅ requestPredicates. Если условия Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ - Ρ‚ΠΎ json ΠΈΠ· response.data (Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ fill) сСриализуСтся Π² protobuf ΠΈ отдаётся Π² качСствС ΠΎΡ‚Π²Π΅Ρ‚Π°.

Алгоритм Ρ€Π°Π±ΠΎΡ‚Ρ‹:

  1. Поиск ΠΌΠΎΠΊΠ°(-ΠΎΠ²) ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°
  2. Валидация body
  3. Поиск state ΠΏΠΎ ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρƒ
  4. ΠŸΠΎΠ΄ΡΡ‚Π°Π½ΠΎΠ²ΠΊΠ° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π² шаблон ΠΎΡ‚Π²Π΅Ρ‚Π°
  5. ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡ state
  6. ΠžΡ‚Π΄Π°Ρ‡Π° response

ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ GRPC Π·Π°Π³Π»ΡƒΡˆΠ΅ΠΊ

{
    "name": "Sample stub",
    "scope": "..",
    "service": "test",
    "methodName": "/pos-loans/api/cl/get_partner_lead_info",
    "seed": {
        "integrationId": "%{randomString(20)}" //ΠΏΡ€ΠΈΠΌΠ΅Ρ€
    },
    "state": {
      // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
    },
    "requestCodecs": "..", //proto-Ρ„Π°ΠΉΠ» схСмы запроса Π² base64
    "requestClass": "..", //имя Ρ‚ΠΈΠΏΠ° запроса ΠΈΠ· proto Ρ„Π°ΠΉΠ»Π°
    "responseCodecs": "..", //proto-Ρ„Π°ΠΉΠ» схСмы ΠΎΡ‚Π²Π΅Ρ‚Π° Π² base64
    "responseClass": "..", //имя Ρ‚ΠΈΠΏΠ° ΠΎΡ‚Π²Π΅Ρ‚Π° ΠΈΠ· proto Ρ„Π°ΠΉΠ»Π°
    "requestPredicates": {
        "meta.id": {"==": 42}
    },
    "persist": {
      // ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ состояния
    },
    "response": {
        "mode": "fill",
        "data": {
            "code": 0,
            "credit_amount": 802400,
            "credit_term": 120,
            "interest_rate": 13.9,
            "partnum": "CL3.15"
        },
        "delay": "1 second"
    }
}

Эмуляция ΡˆΠΈΠ½Π½Ρ‹Ρ… сСрвисов

Алгоритм Ρ€Π°Π±ΠΎΡ‚Ρ‹:

  1. Поиск мока по source
  2. Поиск state ΠΏΠΎ ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρƒ
  3. Валидация входящСго сообщСния
  4. ΠŸΠΎΠ΄ΡΡ‚Π°Π½ΠΎΠ²ΠΊΠ° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π² шаблон ΠΎΡ‚Π²Π΅Ρ‚Π°
  5. ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡ state
  6. ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° response
  7. Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ»Π±Π΅ΠΊΠΎΠ² (см. Ρ€Π°Π·Π΄Π΅Π» "конфигурация ΠΊΠΎΠ»Π±Π΅ΠΊΠΎΠ²")

ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ

Π Π°Π±ΠΎΡ‚Π° с очСрСдями

ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ ΠΌΠΎΠΊΠ°

Для input ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ€Π΅ΠΆΠΈΠΌΡ‹:

  • raw
  • json
  • xml
  • jlens
  • xpath

Для output ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ€Π΅ΠΆΠΈΠΌΡ‹:

  • raw
  • json
  • xml
{
  "name": "ΠŸΡ€ΠΈΡˆΠ»Π° вСсна", 
  "service": "test",
  "source": "rmq_example_autobroker_decision", //source ΠΈΠ· ΠΊΠΎΠ½Ρ„ΠΈΠ³Π°
  "input": {
    "mode": .. //ΠΊΠ°ΠΊ для HTTP Π·Π°Π³Π»ΡƒΡˆΠ΅ΠΊ
    "payload": .. //ΠΊΠ°ΠΊ body для HTTP Π·Π°Π³Π»ΡƒΡˆΠ΅ΠΊ
  },
  "state": {
    // ΠŸΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚Ρ‹
  },
  "persist": { //ΠžΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ
    // ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ состояния
  },
  "destination": "rmq_example_q1", // destination ΠΈΠ· ΠΊΠΎΠ½Ρ„ΠΈΠ³Π°, ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ
  "output": { //ΠžΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ  
    "mode": "raw",
    "payload": "..",
    "delay": "1 second"
  },
  "callback": { .. }
}

ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ ΠΊΠΎΠ»Π±Π΅ΠΊΠΎΠ²

Для ΠΈΠΌΠΈΡ‚Π°Ρ†ΠΈΠΈ повСдСния Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΌΠΈΡ€Π° ΠΈΠ½ΠΎΠ³Π΄Π° Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Π²Ρ‹Π·ΠΎΠ² HTTP сСрвиса (ΠΏΡ€ΠΈΠΌΠ΅Ρ€ - Π·Π°Π±Ρ€Π°Ρ‚ΡŒ GBO ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ сообщСниС) ΠΈΠ»ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ сообщСния Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ. Для этого ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠ»Π±Π΅ΠΊΠΈ. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π²Ρ‹Π·ΠΎΠ²Π° сСрвиса ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈ нСобходимости Ρ€Π°ΡΠΏΠ°Ρ€ΡΠΈΡ‚ΡŒ ΠΈ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Π² состояниС. КоллбСки ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ состяниС Π²Ρ‹Π·Π²Π°Π²ΡˆΠ΅Π³ΠΎ.

Π’Ρ‹Π·ΠΎΠ² HTTP ΠΌΠ΅Ρ‚ΠΎΠ΄Π°

Для request ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ€Π΅ΠΆΠΈΠΌΡ‹

  • no_body
  • raw
  • json
  • xml

Для response ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ€Π΅ΠΆΠΈΠΌΡ‹

  • json
  • xml

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅! Π’ всю Ρ†Π΅ΠΏΠΎΡ‡ΠΊΡƒ ΠΊΠΎΠ»Π±Π΅ΠΊΠΎΠ² пСрСдаётся ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ стСйт, ΠΎΠ½ Π½Π΅ измСняСтся Π±Π»ΠΎΠΊΠΎΠΌ perist (!!!)

{
  "type": "http",
  "request": {
    "url": "http://some.host/api/v2/peka",
    "method": "POST",
    "headers": {"Content-Type": "application/json"},
    "mode": "json",
    "body": {
      "trace_id": "42",
      "account_number": "228"
    }
  },
  "responseMode": "json" | "xml", //ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ Π±Π»ΠΎΠΊΠ° persist
  "persist": { //ΠžΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ
    // ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ состояния
  },
  "delay": "1 second", //Π—Π°Π΄Π΅Ρ€ΠΆΠΊΠ° ΠŸΠ•Π Π•Π” Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ»Π±Π΅ΠΊΠ°, ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ
  "callback": { .. } //ΠžΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ
}

ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° сообщСния

Для output ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Ρ€Π΅ΠΆΠΈΠΌΡ‹:

  • raw
  • json
  • xml
{
  "type": "message",
  "destination": "rmq_example_q1", // destination ΠΈΠ· ΠΊΠΎΠ½Ρ„ΠΈΠ³Π°
  "output": {
    "mode": "raw",
    "payload": ".."
  },
  "callback": { .. } //ΠžΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎ
}

About

Flexible mock server

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 5