From b2c4be803d567f1127891b72061eaf5ce2213f71 Mon Sep 17 00:00:00 2001
From: sabevzenko
Date: Wed, 18 Oct 2023 13:15:16 +0300
Subject: [PATCH] scenario docs
scenario docs
---
.mapping.json | 4 +
docs/eng/http-generator.md | 44 +++
docs/eng/scenario-http-generator.md | 517 ++++++++++++++++++++++++++++
docs/index.md | 4 +-
docs/rus/http-generator.md | 44 +++
docs/rus/index.md | 2 +
docs/rus/scenario-http-generator.md | 517 ++++++++++++++++++++++++++++
7 files changed, 1131 insertions(+), 1 deletion(-)
create mode 100644 docs/eng/http-generator.md
create mode 100644 docs/eng/scenario-http-generator.md
create mode 100644 docs/rus/http-generator.md
create mode 100644 docs/rus/scenario-http-generator.md
diff --git a/.mapping.json b/.mapping.json
index c0b3d22fd..94c8ee5f9 100644
--- a/.mapping.json
+++ b/.mapping.json
@@ -221,10 +221,12 @@
"docs/eng/architecture.md":"load/projects/pandora/docs/eng/architecture.md",
"docs/eng/config.md":"load/projects/pandora/docs/eng/config.md",
"docs/eng/custom.md":"load/projects/pandora/docs/eng/custom.md",
+ "docs/eng/http-generator.md":"load/projects/pandora/docs/eng/http-generator.md",
"docs/eng/install.md":"load/projects/pandora/docs/eng/install.md",
"docs/eng/load-profile.md":"load/projects/pandora/docs/eng/load-profile.md",
"docs/eng/performance.md":"load/projects/pandora/docs/eng/performance.md",
"docs/eng/providers.md":"load/projects/pandora/docs/eng/providers.md",
+ "docs/eng/scenario-http-generator.md":"load/projects/pandora/docs/eng/scenario-http-generator.md",
"docs/eng/tuturial.md":"load/projects/pandora/docs/eng/tuturial.md",
"docs/images/architecture.graphml":"load/projects/pandora/docs/images/architecture.graphml",
"docs/images/architecture.png":"load/projects/pandora/docs/images/architecture.png",
@@ -239,11 +241,13 @@
"docs/rus/architecture.md":"load/projects/pandora/docs/rus/architecture.md",
"docs/rus/config.md":"load/projects/pandora/docs/rus/config.md",
"docs/rus/custom.md":"load/projects/pandora/docs/rus/custom.md",
+ "docs/rus/http-generator.md":"load/projects/pandora/docs/rus/http-generator.md",
"docs/rus/index.md":"load/projects/pandora/docs/rus/index.md",
"docs/rus/install.md":"load/projects/pandora/docs/rus/install.md",
"docs/rus/load-profile.md":"load/projects/pandora/docs/rus/load-profile.md",
"docs/rus/performance.md":"load/projects/pandora/docs/rus/performance.md",
"docs/rus/providers.md":"load/projects/pandora/docs/rus/providers.md",
+ "docs/rus/scenario-http-generator.md":"load/projects/pandora/docs/rus/scenario-http-generator.md",
"docs/rus/tuturial.md":"load/projects/pandora/docs/rus/tuturial.md",
"examples/connect.yaml":"load/projects/pandora/examples/connect.yaml",
"examples/custom_pandora/custom.yaml":"load/projects/pandora/examples/custom_pandora/custom.yaml",
diff --git a/docs/eng/http-generator.md b/docs/eng/http-generator.md
new file mode 100644
index 000000000..43d3ad7b4
--- /dev/null
+++ b/docs/eng/http-generator.md
@@ -0,0 +1,44 @@
+[Home](../index.md)
+
+---
+
+# HTTP generator
+
+Full http (http2) generator config
+
+```yaml
+gun:
+ type: http
+ target: '[hostname]:443'
+ ssl: true
+ connect-ssl: false # If true, Pandora accepts any certificate presented by the server and any host name in that certificate. Default: false
+ tls-handshake-timeout: 1s # Maximum waiting time for a TLS handshake. Default: 1s
+ disable-keep-alives: false # If true, disables HTTP keep-alives. Default: false
+ disable-compression: true # If true, prevents the Transport from requesting compression with an "Accept-Encoding: gzip" request header. Default: true
+ max-idle-conns: 0 # Maximum number of idle (keep-alive) connections across all hosts. Zero means no limit. Default: 0
+ max-idle-conns-per-host: 2 # Controls the maximum idle (keep-alive) connections to keep per-host. Default: 2
+ idle-conn-timeout: 90s # Maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. Zero means no limit. Default: 90s
+ response-header-timeout: 0 # Amount of time to wait for a server's response headers after fully writing the request (including its body, if any). Zero means no timeout. Default: 0
+ expect-continue-timeout: 1s # Amount of time to wait for a server's first response headers after fully writing the request headers if the request has an "Expect: 100-continue" header. Zero means no timeout. Default: 1s
+ dial:
+ timeout: 1s # TCP connect timeout. Default: 3s
+ dns-cache: true # Enable DNS cache, remember remote address on first try, and use it in the future. Default: true
+ dual-stack: true # IPv4 is tried soon if IPv6 appears to be misconfigured and hanging. Default: true
+ fallback-delay: 300ms # The amount of time to wait for IPv6 to succeed before falling back to IPv4. Default 300ms
+ keep-alive: 120s # Interval between keep-alive probes for an active network connection Default: 120s
+ answlog:
+ enabled: true
+ path: ./answ.log
+ filter: all # all - all http codes, warning - log 4xx and 5xx, error - log only 5xx. Default: error
+ auto-tag:
+ enabled: true
+ uri-elements: 2 # URI elements used to autotagging. Default: 2
+ no-tag-only: true # When true, autotagged only ammo that has no tag before. Default: true
+ httptrace:
+ dump: true # calculate responce bytes
+ trace: true # calculate different request stages: connect time, send time, latency, request bytes
+```
+
+---
+
+[Home](../index.md)
diff --git a/docs/eng/scenario-http-generator.md b/docs/eng/scenario-http-generator.md
new file mode 100644
index 000000000..1a6ad077a
--- /dev/null
+++ b/docs/eng/scenario-http-generator.md
@@ -0,0 +1,517 @@
+[Home](../index.md)
+
+---
+
+# Scenario generator / HTTP
+
+- [Configuration](#configuration)
+ - [Генератор](#генератор)
+ - [Провайдер](#провайдер)
+- [Описание формата сценариев](#описание-формата-сценариев)
+ - [Описание формата в HCL](#описание-формата-в-hcl)
+ - [Пример в YAML](#пример-в-yaml)
+- [Возможности](#возможности)
+ - [Requests](#requests)
+ - [Шаблонизатор](#шаблонизатор)
+ - [Имена переменных в шаблонрах](#имена-переменных-в-шаблонах)
+ - [Preprocessors](#preprocessors)
+ - [Postprocessors](#postprocessors)
+ - [var/jsonpath](#varjsonpath)
+ - [var/xpath](#varxpath)
+ - [var/header](#varheader)
+ - [assert/response](#assertresponse)
+ - [Scenarios](#scenarios)
+ - [Sources](#sources)
+ - [csv file](#csv-file)
+ - [json file](#json-file)
+ - [variables](#variables)
+
+## Configuration
+
+Вам необходимо использовать генератор и провайдер типа `http/scenario`
+
+```yaml
+pools:
+ - id: Pool name
+ gun:
+ type: http/scenario
+ target: localhost:80
+ ammo:
+ type: http/scenario
+ file: payload.hcl
+```
+
+### Генератор
+
+Минимальная конфигурация генератора выглядит так
+
+```yaml
+gun:
+ type: http/scenario
+ target: localhost:80
+```
+
+Так же есть `type: http2/scenario` генератор
+
+```yaml
+gun:
+ type: http2/scenario
+ target: localhost:80
+```
+
+Для сценарного генератора поддерживаются все настройки обычного [HTTP генератора](http-generator.md)
+
+### Провайдер
+
+Провайдер принимает всего один параметр - путь до файла с описанием сценария
+
+```yaml
+ammo:
+ type: http/scenario
+ file: payload.hcl
+```
+
+Поддерживает файлы расширений
+
+- hcl
+- yaml
+- json
+
+## Описание формата сценариев
+
+Поддерживает форматы
+
+- hcl
+- yaml
+- json
+
+### Общий принцип
+
+В одном файле можно описывать несколько сценариев. У сценария есть имя по которому один сценарий отличается от другого.
+
+Сценарий - это последовательность запросов. То есть вам потребуется описать в сценарии какие запросы в каком порядке
+должны выполняться.
+
+Запрос - HTTP запрос. То есть имеет все стандартные поля HTTP запроса. И дополнительные для работы в сценарии
+
+### Описание формата в HCL
+
+```terraform
+variable_source "source_name" "file/csv" {
+ file = "file.csv"
+ fields = ["id", "name"]
+ ignore_first_line = true
+ delimiter = ","
+}
+
+request "request_name" {
+ method = "POST"
+ uri = "/uri"
+ headers = {
+ HeaderName = "header value"
+ }
+ tag = "tag"
+ body = <
+EOF
+ templater = "text"
+
+ preprocessor {
+ mapping = {
+ new_var = "source.var_name[next].0"
+ }
+ }
+ postprocessor "var/jsonpath" {
+ mapping = {
+ new_var = "$.auth_key"
+ }
+ }
+}
+
+
+scenario "scenario_name" {
+ weight = 1
+ min_waiting_time = 1000
+ requests = [
+ "request_name",
+ ]
+}
+```
+
+### Пример в YAML
+
+```yaml
+variable_sources:
+ - type: "file/csv"
+ name: "source_name"
+ ignore_first_line: true
+ delimiter: ","
+ file: "file.csv"
+ fields: [ "id", "name" ]
+
+requests:
+ - name: "request_name"
+ uri: '/uri'
+ method: POST
+ headers:
+ Header-Name: "header value"
+ tag: tag
+ body: ''
+ preprocessor:
+ mapping:
+ new_var: source.var_name[next].0
+ templater:
+ type: text
+ postprocessors:
+ - type: var/jsonpath
+ mapping:
+ token: "$.auth_key"
+
+scenarios:
+ - name: scenario_name
+ weight: 1
+ min_waiting_time: 1000
+ requests: [
+ request_name
+ ]
+```
+
+## Возможности
+
+### Requests
+
+Поля
+
+- method
+- uri
+- headers
+- body
+- **name**
+- tag
+- templater
+- preprocessors
+- postprocessors
+
+### Шаблонизатор
+
+Поля `uri`, `headers`, `body` шаблонризируются.
+
+Используется стандартный go template.
+
+#### Имена переменных в шаблонах
+
+Имена переменных имеют полный путь их определения.
+
+Например
+
+Переменная `users` из источника `user_file` - `{% raw %}{{.source.user_file.users}}{% endraw %}`
+
+Переменная `token` из постпроцессора запроса `list_req` - `{% raw %}{{.request.list_req.postprocessor.token}}{% endraw %}`
+
+Переменная `item` из препроцессора запроса `list_req` - `{% raw %}{{.request.list_req.preprocessor.item}}{% endraw %}`
+
+#### Preprocessors
+
+Препроцессор - действия выполняются перед шаблонизацией
+
+Используется для нового маппинга переменных
+
+У препроцессора есть возможность работать с массивами с помощью модификаторов
+-
+
+- next
+- last
+- rand
+
+##### yaml
+
+```yaml
+requests:
+ - name: req_name
+ ...
+ preprocessor:
+ mapping:
+ user_id: source.users[next].id
+```
+
+##### hcl
+
+```terraform
+request "req_name" {
+ preprocessor {
+ mapping = {
+ user_id = "source.users[next].id"
+ }
+ }
+}
+```
+
+#### Postprocessors
+
+##### var/jsonpath
+
+Пример hcl
+
+```terraform
+postprocessor "var/jsonpath" {
+ mapping = {
+ token = "$.auth_key"
+ }
+}
+```
+
+##### var/xpath
+
+```terraform
+postprocessor "var/xpath" {
+ mapping = {
+ data = "//div[@class='data']"
+ }
+}
+```
+
+##### var/header
+
+Создает новую переменную из заголовков ответа
+
+Есть возможность через pipe указывать простейшие строковые манипуляции
+
+- lower
+- upper
+- substr(from, length)
+- replace(search, replace)
+
+```terraform
+postprocessor "var/header" {
+ mapping = {
+ ContentType = "Content-Type|upper"
+ httpAuthorization = "Http-Authorization"
+ }
+}
+```
+
+##### assert/response
+
+Проверяет значения заголовков и тела
+
+Если матчинг не срабатывает, прекращает дальнейшее выполнение сценария
+
+```terraform
+postprocessor "assert/response" {
+ headers = {
+ "Content-Type" = "application/json"
+ }
+ body = ["token"]
+ status_code = 200
+
+ size {
+ val = 10000
+ op = ">"
+ }
+}
+```
+
+### Scenarios
+
+Минимальные поля для сценария - имя и перечень запросов
+
+```terraform
+scenario "scenario_name" {
+ requests = [
+ "list_req",
+ "order_req",
+ "order_req",
+ "order_req"
+ ]
+}
+```
+
+Можно указать мултипликатор повторения запросов
+
+```terraform
+scenario "scenario_name" {
+ requests = [
+ "list_req",
+ "order_req(3)"
+ ]
+}
+```
+
+Можно указать задержку sleep(). Параметр в миллисекундах
+
+```terraform
+scenario "scenario_name" {
+ requests = [
+ "list_req",
+ "sleep(100)",
+ "order_req(3)"
+ ]
+}
+```
+
+Вторым аргументом в запросы указывается sleep для запросов с мултипликаторами
+
+```terraform
+scenario "scenario_name" {
+ requests = [
+ "list_req",
+ "sleep(100)",
+ "order_req(3, 100)"
+ ]
+}
+```
+
+Параметр `min_waiting_time` описывает минимальное время выполнения сценария. То есть будет добавлен sleep в конце всего
+сценария, если сценарий выполнится быстрее этого параметра.
+
+```terraform
+scenario "scenario_name" {
+ min_waiting_time = 1000
+ requests = [
+ "list_req",
+ "sleep(100)",
+ "order_req(3, 100)"
+ ]
+}
+```
+
+В одном файле можно описывать множество сценариев
+
+Параметр `weight` - вес распределения каждого сценария. Чем больше вес, тем чаще будет выполняться сценарий.
+
+
+```terraform
+scenario "scenario_first" {
+ weight = 1
+ requests = [
+ "auth_req(1, 100)",
+ "list_req(1, 100)",
+ "order_req(3, 100)"
+ ]
+}
+
+scenario "scenario_second" {
+ weight = 50
+ requests = [
+ "mainpage",
+ ]
+}
+
+```
+
+### Sources
+
+Источники переменных
+
+#### csv file
+
+Пример
+
+```terraform
+variable_source "users" "file/csv" {
+ file = "users.csv" # required
+ fields = ["user_id", "name", "pass"] # optional
+ ignore_first_line = true # optional
+ delimiter = "," # optional
+}
+```
+
+Создание источника из csv. Добавление ему имени `users`.
+
+Использование переменных из данного источника
+
+```gotempate
+{% raw %}{{.source.users[0].user_id}}{% endraw %}
+```
+
+Параметр `fields` является необязательным.
+
+Если этого параметра нет, то в качестве имен полей будет использоваться имена в первой строке csv файла,
+если `ignore_first_line = false`.
+
+Если `ignore_first_line = true` и отсутствуют поля, то в качестве имен будут использоваться порядковые номер
+
+```gotempate
+{% raw %}{{.source.users[0].0}}{% endraw %}
+```
+
+#### json file
+
+Пример
+
+```terraform
+variable_source "users" "file/json" {
+ file = "users.json" # required
+}
+```
+
+Создание источника из json файла. Добавление ему имени `users`.
+
+Файл должен содержать любой валидный json. Например:
+
+```json
+{
+ "data": [
+ {
+ "id": 1,
+ "name": "user1"
+ },
+ {
+ "id": 2,
+ "name": "user2"
+ }
+ ]
+}
+```
+
+Использование переменных из данного источника
+
+```gotempate
+{% raw %}{{.source.users.data[next].id}}{% endraw %}
+```
+
+Или пример с массивом
+
+```json
+ [
+ {
+ "id": 1,
+ "name": "user1"
+ },
+ {
+ "id": 2,
+ "name": "user2"
+ }
+]
+```
+
+Использование переменных из данного источника
+
+```gotempate
+{% raw %}{{.source.users[next].id}}{% endraw %}
+```
+
+#### variables
+
+Пример
+
+```terraform
+variable_source "variables" "variables" {
+ variables = {
+ host = localhost
+ port = 8090
+ }
+}
+```
+
+Создание источника с переменными. Добавление ему имени `variables`.
+
+Использование переменных из данного источника
+
+```gotempate
+{% raw %}{{.source.variables.host}}:{{.source.variables.port}}{% endraw %}
+```
+
+---
+
+[Home](../index.md)
diff --git a/docs/index.md b/docs/index.md
index 8f98ce784..2582749e8 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -9,7 +9,9 @@ write your own load scenarios in Go, compiling them just before your test.
- [Configuration](eng/config.md)
- [Your first test](eng/tuturial.md)
- [Load profile](eng/load-profile.md)
-- [HTTP Ammo providers](eng/providers.md)
+- [HTTP providers](eng/providers.md)
+- [HTTP generators](eng/http-generator.md)
+- [Scenario generator / HTTP](eng/scenario-http-generator.md)
- [Custom guns](eng/custom.md)
- [Pandora’s performance](eng/performance.md)
- [Architectural overview](eng/architecture.md)
diff --git a/docs/rus/http-generator.md b/docs/rus/http-generator.md
new file mode 100644
index 000000000..31ccba8c0
--- /dev/null
+++ b/docs/rus/http-generator.md
@@ -0,0 +1,44 @@
+[Домой](index.md)
+
+---
+
+# HTTP генератор
+
+Полный конфиг http (http2) генератора
+
+```yaml
+gun:
+ type: http
+ target: '[hostname]:443'
+ ssl: true
+ connect-ssl: false # If true, Pandora accepts any certificate presented by the server and any host name in that certificate. Default: false
+ tls-handshake-timeout: 1s # Maximum waiting time for a TLS handshake. Default: 1s
+ disable-keep-alives: false # If true, disables HTTP keep-alives. Default: false
+ disable-compression: true # If true, prevents the Transport from requesting compression with an "Accept-Encoding: gzip" request header. Default: true
+ max-idle-conns: 0 # Maximum number of idle (keep-alive) connections across all hosts. Zero means no limit. Default: 0
+ max-idle-conns-per-host: 2 # Controls the maximum idle (keep-alive) connections to keep per-host. Default: 2
+ idle-conn-timeout: 90s # Maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. Zero means no limit. Default: 90s
+ response-header-timeout: 0 # Amount of time to wait for a server's response headers after fully writing the request (including its body, if any). Zero means no timeout. Default: 0
+ expect-continue-timeout: 1s # Amount of time to wait for a server's first response headers after fully writing the request headers if the request has an "Expect: 100-continue" header. Zero means no timeout. Default: 1s
+ dial:
+ timeout: 1s # TCP connect timeout. Default: 3s
+ dns-cache: true # Enable DNS cache, remember remote address on first try, and use it in the future. Default: true
+ dual-stack: true # IPv4 is tried soon if IPv6 appears to be misconfigured and hanging. Default: true
+ fallback-delay: 300ms # The amount of time to wait for IPv6 to succeed before falling back to IPv4. Default 300ms
+ keep-alive: 120s # Interval between keep-alive probes for an active network connection Default: 120s
+ answlog:
+ enabled: true
+ path: ./answ.log
+ filter: all # all - all http codes, warning - log 4xx and 5xx, error - log only 5xx. Default: error
+ auto-tag:
+ enabled: true
+ uri-elements: 2 # URI elements used to autotagging. Default: 2
+ no-tag-only: true # When true, autotagged only ammo that has no tag before. Default: true
+ httptrace:
+ dump: true # calculate responce bytes
+ trace: true # calculate different request stages: connect time, send time, latency, request bytes
+```
+
+---
+
+[Домой](index.md)
diff --git a/docs/rus/index.md b/docs/rus/index.md
index 2d4c338f3..3504f7ed5 100644
--- a/docs/rus/index.md
+++ b/docs/rus/index.md
@@ -9,6 +9,8 @@ Pandora - это высокопроизводительный генератор
- [Первый тест](tuturial.md)
- [Профиль нагрузки](load-profile.md)
- [HTTP providers](providers.md)
+- [HTTP генератор](http-generator.md)
+- [Сценарный генератор / HTTP](scenario-http-generator.md)
- [Custom](custom.md)
- [Производительность Pandora](performance.md)
- [Архитектура](architecture.md)
diff --git a/docs/rus/scenario-http-generator.md b/docs/rus/scenario-http-generator.md
new file mode 100644
index 000000000..19f28d433
--- /dev/null
+++ b/docs/rus/scenario-http-generator.md
@@ -0,0 +1,517 @@
+[Домой](index.md)
+
+---
+
+# Сценарный генератор / HTTP
+
+- [Конфигурация](#конфигурация)
+ - [Генератор](#генератор)
+ - [Провайдер](#провайдер)
+- [Описание формата сценариев](#описание-формата-сценариев)
+ - [Описание формата в HCL](#описание-формата-в-hcl)
+ - [Пример в YAML](#пример-в-yaml)
+- [Возможности](#возможности)
+ - [Requests](#requests)
+ - [Шаблонизатор](#шаблонизатор)
+ - [Имена переменных в шаблонрах](#имена-переменных-в-шаблонах)
+ - [Preprocessors](#preprocessors)
+ - [Postprocessors](#postprocessors)
+ - [var/jsonpath](#varjsonpath)
+ - [var/xpath](#varxpath)
+ - [var/header](#varheader)
+ - [assert/response](#assertresponse)
+ - [Scenarios](#scenarios)
+ - [Sources](#sources)
+ - [csv file](#csv-file)
+ - [json file](#json-file)
+ - [variables](#variables)
+
+## Конфигурация
+
+Вам необходимо использовать генератор и провайдер типа `http/scenario`
+
+```yaml
+pools:
+ - id: Pool name
+ gun:
+ type: http/scenario
+ target: localhost:80
+ ammo:
+ type: http/scenario
+ file: payload.hcl
+```
+
+### Генератор
+
+Минимальная конфигурация генератора выглядит так
+
+```yaml
+gun:
+ type: http/scenario
+ target: localhost:80
+```
+
+Так же есть `type: http2/scenario` генератор
+
+```yaml
+gun:
+ type: http2/scenario
+ target: localhost:80
+```
+
+Для сценарного генератора поддерживаются все настройки обычного [HTTP генератора](http-generator.md)
+
+### Провайдер
+
+Провайдер принимает всего один параметр - путь до файла с описанием сценария
+
+```yaml
+ammo:
+ type: http/scenario
+ file: payload.hcl
+```
+
+Поддерживает файлы расширений
+
+- hcl
+- yaml
+- json
+
+## Описание формата сценариев
+
+Поддерживает форматы
+
+- hcl
+- yaml
+- json
+
+### Общий принцип
+
+В одном файле можно описывать несколько сценариев. У сценария есть имя по которому один сценарий отличается от другого.
+
+Сценарий - это последовательность запросов. То есть вам потребуется описать в сценарии какие запросы в каком порядке
+должны выполняться.
+
+Запрос - HTTP запрос. То есть имеет все стандартные поля HTTP запроса. И дополнительные для работы в сценарии
+
+### Описание формата в HCL
+
+```terraform
+variable_source "source_name" "file/csv" {
+ file = "file.csv"
+ fields = ["id", "name"]
+ ignore_first_line = true
+ delimiter = ","
+}
+
+request "request_name" {
+ method = "POST"
+ uri = "/uri"
+ headers = {
+ HeaderName = "header value"
+ }
+ tag = "tag"
+ body = <
+EOF
+ templater = "text"
+
+ preprocessor {
+ mapping = {
+ new_var = "source.var_name[next].0"
+ }
+ }
+ postprocessor "var/jsonpath" {
+ mapping = {
+ new_var = "$.auth_key"
+ }
+ }
+}
+
+
+scenario "scenario_name" {
+ weight = 1
+ min_waiting_time = 1000
+ requests = [
+ "request_name",
+ ]
+}
+```
+
+### Пример в YAML
+
+```yaml
+variable_sources:
+ - type: "file/csv"
+ name: "source_name"
+ ignore_first_line: true
+ delimiter: ","
+ file: "file.csv"
+ fields: [ "id", "name" ]
+
+requests:
+ - name: "request_name"
+ uri: '/uri'
+ method: POST
+ headers:
+ Header-Name: "header value"
+ tag: tag
+ body: '