dodo/README.md

12 KiB

Dodo - A Fast and Easy-to-Use HTTP Benchmarking Tool

Table of Contents

Installation

Pull the latest Dodo image from Docker Hub:

docker pull aykhans/dodo:latest

To use Dodo with Docker and a local config file, mount the config file as a volume and pass it as an argument:

docker run -v /path/to/config.json:/config.json aykhans/dodo -f /config.json

If you're using a remote config file via URL, you don't need to mount a volume:

docker run aykhans/dodo -f https://raw.githubusercontent.com/aykhans/dodo/main/config.yaml

Using Pre-built Binaries

Download the latest binaries from the releases section.

Building from Source

To build Dodo from source, ensure you have Go 1.24+ installed.

go install -ldflags "-s -w" github.com/aykhans/dodo@latest

Usage

Dodo supports CLI arguments, configuration files (JSON/YAML), or a combination of both. If both are used, CLI arguments take precedence.

1. CLI Usage

Send 1000 GET requests to https://example.com with 10 parallel dodos (threads), each with a timeout of 2 seconds, within a maximum duration of 1 minute:

dodo -u https://example.com -m GET -d 10 -r 1000 -o 1m -t 2s

With Docker:

docker run --rm -i aykhans/dodo -u https://example.com -m GET -d 10 -r 1000 -o 1m -t 2s

2. Config File Usage

Send 1000 GET requests to https://example.com with 10 parallel dodos (threads), each with a timeout of 800 milliseconds, within a maximum duration of 250 seconds:

2.1 YAML/YML Example

method: "GET"
url: "https://example.com"
yes: false
timeout: "800ms"
dodos: 10
requests: 1000
duration: "250s"
skip_verify: false

params:
    # A random value will be selected from the list for first "key1" param on each request
    # And always "value" for second "key1" param on each request
    # e.g. "?key1=value2&key1=value"
    - key1: ["value1", "value2", "value3", "value4"]
    - key1: "value"

    # A random value will be selected from the list for param "key2" on each request
    # e.g. "?key2=value2"
    - key2: ["value1", "value2"]

headers:
    # A random value will be selected from the list for first "key1" header on each request
    # And always "value" for second "key1" header on each request
    # e.g. "key1: value3", "key1: value"
    - key1: ["value1", "value2", "value3", "value4"]
    - key1: "value"

    # A random value will be selected from the list for header "key2" on each request
    # e.g. "key2: value2"
    - key2: ["value1", "value2"]

cookies:
    # A random value will be selected from the list for first "key1" cookie on each request
    # And always "value" for second "key1" cookie on each request
    # e.g. "key1=value4; key1=value"
    - key1: ["value1", "value2", "value3", "value4"]
    - key1: "value"

    # A random value will be selected from the list for cookie "key2" on each request
    # e.g. "key2=value1"
    - key2: ["value1", "value2"]

body: "body-text"
# OR
# A random body value will be selected from the list for each request
body:
    - "body-text1"
    - "body-text2"
    - "body-text3"

proxy: "http://example.com:8080"
# OR
# A random proxy will be selected from the list for each request
proxy:
    - "http://example.com:8080"
    - "http://username:password@example.com:8080"
    - "socks5://example.com:8080"
    - "socks5h://example.com:8080"
dodo -f /path/config.yaml
# OR
dodo -f https://example.com/config.yaml

With Docker:

docker run --rm -i -v /path/to/config.yaml:/config.yaml aykhans/dodo -f /config.yaml
# OR
docker run --rm -i aykhans/dodo -f https://example.com/config.yaml

2.2 JSON Example

{
    "method": "GET",
    "url": "https://example.com",
    "yes": false,
    "timeout": "800ms",
    "dodos": 10,
    "requests": 1000,
    "duration": "250s",
    "skip_verify": false,

    "params": [
        // A random value will be selected from the list for first "key1" param on each request
        // And always "value" for second "key1" param on each request
        // e.g. "?key1=value2&key1=value"
        { "key1": ["value1", "value2", "value3", "value4"] },
        { "key1": "value" },

        // A random value will be selected from the list for param "key2" on each request
        // e.g. "?key2=value2"
        { "key2": ["value1", "value2"] },
    ],

    "headers": [
        // A random value will be selected from the list for first "key1" header on each request
        // And always "value" for second "key1" header on each request
        // e.g. "key1: value3", "key1: value"
        { "key1": ["value1", "value2", "value3", "value4"] },
        { "key1": "value" },

        // A random value will be selected from the list for header "key2" on each request
        // e.g. "key2: value2"
        { "key2": ["value1", "value2"] },
    ],

    "cookies": [
        // A random value will be selected from the list for first "key1" cookie on each request
        // And always "value" for second "key1" cookie on each request
        // e.g. "key1=value4; key1=value"
        { "key1": ["value1", "value2", "value3", "value4"] },
        { "key1": "value" },

        // A random value will be selected from the list for cookie "key2" on each request
        // e.g. "key2=value1"
        { "key2": ["value1", "value2"] },
    ],

    "body": "body-text",
    // OR
    // A random body value will be selected from the list for each request
    "body": ["body-text1", "body-text2", "body-text3"],

    "proxy": "http://example.com:8080",
    // OR
    // A random proxy will be selected from the list for each request
    "proxy": [
        "http://example.com:8080",
        "http://username:password@example.com:8080",
        "socks5://example.com:8080",
        "socks5h://example.com:8080",
    ],
}
dodo -f /path/config.json
# OR
dodo -f https://example.com/config.json

With Docker:

docker run --rm -i -v /path/to/config.json:/config.json aykhans/dodo
# OR
docker run --rm -i aykhans/dodo -f https://example.com/config.json

3. CLI & Config File Combination

CLI arguments override config file values:

dodo -f /path/to/config.yaml -u https://example.com -m GET -d 10 -r 1000 -o 1m -t 5s

With Docker:

docker run --rm -i -v /path/to/config.json:/config.json aykhans/dodo -f /config.json -u https://example.com -m GET -d 10 -r 1000 -o 1m -t 5s

Config Parameters Reference

If Headers, Params, Cookies, Body, or Proxy fields have multiple values, each request will choose a random value from the list.

Parameter config file CLI Flag CLI Short Flag Type Description Default
Config file -config-file -f String Path to local config file or http(s) URL of the config file -
Yes yes -yes -y Boolean Answer yes to all questions false
URL url -url -u String URL to send the request to -
Method method -method -m String HTTP method GET
Dodos (Threads) dodos -dodos -d UnsignedInteger Number of dodos (threads) to send requests in parallel 1
Requests requests -requests -r UnsignedInteger Total number of requests to send -
Duration duration -duration -o Time Maximum duration for the test -
Timeout timeout -timeout -t Time Timeout for canceling each request 10s
Params params -param -p [{String: String OR [String]}] Request parameters -
Headers headers -header -H [{String: String OR [String]}] Request headers -
Cookies cookies -cookie -c [{String: String OR [String]}] Request cookies -
Body body -body -b String OR [String] Request body or list of request bodies -
Proxy proxies -proxy -x String OR [String] Proxy URL or list of proxy URLs -
Skip Verify skip_verify -skip-verify Boolean Skip SSL/TLS certificate verification false

Template Functions

Dodo supports template functions in Headers, Params, Cookies, and Body fields. These functions allow you to generate dynamic values for each request.

You can use Go template syntax to include dynamic values in your requests. Here's how to use template functions:

In CLI config:

dodo -u https://example.com -r 1 \
    -header "User-Agent:{{ fakeit_UserAgent }}" \ # e.g. "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"
    -param "username={{ strings_ToUpper fakeit_Username }}" \ # e.g. "username=JOHN BOB"
    -cookie "token={{ fakeit_Password true true true true true 10 }}" \ # e.g. token=1234567890abcdef1234567890abcdef
    -body '{"email":"{{ fakeit_Email }}", "password":"{{ fakeit_Password true true true true true 10 }}"}' # e.g. {"email":"john.doe@example.com", "password":"12rw4d-78d"}

In YAML/YML config:

headers:
    - User-Agent: "{{ fakeit_UserAgent }}" # e.g. "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"
    - "Random-Header-{{fakeit_FirstName}}": "static_value" # e.g. "Random-Header-John: static_value"

cookies:
    - token: "Bearer {{ fakeit_UUID }}" # e.g. "token=Bearer 1234567890abcdef1234567890abcdef"

params:
    - id: "{{ fakeit_Uint }}" # e.g. "id=1234567890"
    - username: "{{ fakeit_Username }}" # e.g. "username=John Doe"

body:
    - '{ "username": "{{ fakeit_Username }}", "password": "{{ fakeit_Password }}" }' # e.g. { "username": "john.doe", "password": "password123" }
    - '{ "email": "{{ fakeit_Email }}", "phone": "{{ fakeit_Phone }}" }' # e.g. { "email": "john.doe@example.com", "phone": "1234567890" }
    - '{{ body_FormData (dict_Str "username" fakeit_Username "password" "secret123") }}' # Creates multipart form data for form submissions, automatically sets the appropriate Content-Type header.

In JSON config:

{
    "headers": [
        { "User-Agent": "{{ fakeit_UserAgent }}" }, // e.g. "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"
    ],
    "body": [
        "{ \"username\": \"{{ strings_RemoveSpaces fakeit_Username }}\", \"password\": \"{{ fakeit_Password }}\" }", // e.g. { "username": "johndoe", "password": "password123" }
        "{{ body_FormData (dict_Str \"username\" fakeit_Username \"password\" \"12345\") }}", // Creates multipart form data for form submissions, automatically sets the appropriate Content-Type header.
    ],
}

For the full list of template functions over 200 functions, refer to the NewFuncMap function in utils/templates.go.