mirror of
https://github.com/aykhans/sarin.git
synced 2026-02-28 06:49:13 +00:00
Add file upload support with body_FormData and file_Base64 functions
- Add FileCache for caching local files and remote URLs in memory - Update body_FormData to accept variadic key-value pairs with file support - Use @ prefix for file paths (local or HTTP/HTTPS URLs) - Use @@ to escape literal @ values - Add file_Base64 function for Base64 encoding files - Update documentation with new syntax and examples
This commit is contained in:
106
docs/examples.md
106
docs/examples.md
@@ -9,6 +9,7 @@ This guide provides practical examples for common Sarin use cases.
|
||||
- [Headers, Cookies, and Parameters](#headers-cookies-and-parameters)
|
||||
- [Dynamic Requests with Templating](#dynamic-requests-with-templating)
|
||||
- [Request Bodies](#request-bodies)
|
||||
- [File Uploads](#file-uploads)
|
||||
- [Using Proxies](#using-proxies)
|
||||
- [Output Formats](#output-formats)
|
||||
- [Docker Usage](#docker-usage)
|
||||
@@ -456,7 +457,7 @@ body: |
|
||||
```sh
|
||||
sarin -U http://example.com/api/upload -r 1000 -c 10 \
|
||||
-M POST \
|
||||
-B '{{ body_FormData (dict_Str "username" "john" "email" "john@example.com") }}'
|
||||
-B '{{ body_FormData "username" "john" "email" "john@example.com" }}'
|
||||
```
|
||||
|
||||
<details>
|
||||
@@ -467,7 +468,7 @@ url: http://example.com/api/upload
|
||||
requests: 1000
|
||||
concurrency: 10
|
||||
method: POST
|
||||
body: '{{ body_FormData (dict_Str "username" "john" "email" "john@example.com") }}'
|
||||
body: '{{ body_FormData "username" "john" "email" "john@example.com" }}'
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -477,7 +478,7 @@ body: '{{ body_FormData (dict_Str "username" "john" "email" "john@example.com")
|
||||
```sh
|
||||
sarin -U http://example.com/api/users -r 1000 -c 10 \
|
||||
-M POST \
|
||||
-B '{{ body_FormData (dict_Str "name" (fakeit_Name) "email" (fakeit_Email) "phone" (fakeit_Phone)) }}'
|
||||
-B '{{ body_FormData "name" (fakeit_Name) "email" (fakeit_Email) "phone" (fakeit_Phone) }}'
|
||||
```
|
||||
|
||||
<details>
|
||||
@@ -488,13 +489,110 @@ url: http://example.com/api/users
|
||||
requests: 1000
|
||||
concurrency: 10
|
||||
method: POST
|
||||
body: '{{ body_FormData (dict_Str "name" (fakeit_Name) "email" (fakeit_Email) "phone" (fakeit_Phone)) }}'
|
||||
body: '{{ body_FormData "name" (fakeit_Name) "email" (fakeit_Email) "phone" (fakeit_Phone) }}'
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
> **Note:** `body_FormData` automatically sets the `Content-Type` header to `multipart/form-data` with the appropriate boundary.
|
||||
|
||||
## File Uploads
|
||||
|
||||
**File upload with multipart form data:**
|
||||
|
||||
Upload a local file:
|
||||
|
||||
```sh
|
||||
sarin -U http://example.com/api/upload -r 100 -c 10 \
|
||||
-M POST \
|
||||
-B '{{ body_FormData "title" "My Document" "document" "@/path/to/file.pdf" }}'
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>YAML equivalent</summary>
|
||||
|
||||
```yaml
|
||||
url: http://example.com/api/upload
|
||||
requests: 100
|
||||
concurrency: 10
|
||||
method: POST
|
||||
body: '{{ body_FormData "title" "My Document" "document" "@/path/to/file.pdf" }}'
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
**Multiple file uploads:**
|
||||
|
||||
```sh
|
||||
sarin -U http://example.com/api/upload -r 100 -c 10 \
|
||||
-M POST \
|
||||
-B '{{ body_FormData "files" "@/path/to/file1.pdf" "files" "@/path/to/file2.pdf" }}'
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>YAML equivalent</summary>
|
||||
|
||||
```yaml
|
||||
url: http://example.com/api/upload
|
||||
requests: 100
|
||||
concurrency: 10
|
||||
method: POST
|
||||
body: |
|
||||
{{ body_FormData
|
||||
"files" "@/path/to/file1.pdf"
|
||||
"files" "@/path/to/file2.pdf"
|
||||
}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
**File from URL:**
|
||||
|
||||
```sh
|
||||
sarin -U http://example.com/api/upload -r 100 -c 10 \
|
||||
-M POST \
|
||||
-B '{{ body_FormData "image" "@https://example.com/photo.jpg" }}'
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>YAML equivalent</summary>
|
||||
|
||||
```yaml
|
||||
url: http://example.com/api/upload
|
||||
requests: 100
|
||||
concurrency: 10
|
||||
method: POST
|
||||
body: '{{ body_FormData "image" "@https://example.com/photo.jpg" }}'
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
> **Note:** Files (local and remote) are cached in memory after the first read, so they are not re-read for every request.
|
||||
|
||||
**Base64 encoded file in JSON body:**
|
||||
|
||||
```sh
|
||||
sarin -U http://example.com/api/upload -r 100 -c 10 \
|
||||
-M POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-B '{"file": "{{ file_Base64 "/path/to/file.pdf" }}", "filename": "document.pdf"}'
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>YAML equivalent</summary>
|
||||
|
||||
```yaml
|
||||
url: http://example.com/api/upload
|
||||
requests: 100
|
||||
concurrency: 10
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
body: '{"file": "{{ file_Base64 "/path/to/file.pdf" }}", "filename": "document.pdf"}'
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Using Proxies
|
||||
|
||||
**Single HTTP proxy:**
|
||||
|
||||
@@ -110,9 +110,63 @@ sarin -U http://example.com/users \
|
||||
|
||||
### Body Functions
|
||||
|
||||
| Function | Description | Example |
|
||||
| ----------------------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------- |
|
||||
| `body_FormData(fields map[string]string)` | Create multipart form data. Automatically sets the `Content-Type` header | `{{ body_FormData (dict_Str "field1" "value1") }}` |
|
||||
| Function | Description | Example |
|
||||
| ------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------ |
|
||||
| `body_FormData(pairs ...string)` | Create multipart form data from key-value pairs. Automatically sets the `Content-Type` header. Values starting with `@` are treated as file references (local path or URL). Use `@@` to escape literal `@`. | `{{ body_FormData "field1" "value1" "file" "@/path/to/file.pdf" }}` |
|
||||
|
||||
**`body_FormData` Details:**
|
||||
|
||||
```yaml
|
||||
# Text fields only
|
||||
body: '{{ body_FormData "username" "john" "email" "john@example.com" }}'
|
||||
|
||||
# Single file upload
|
||||
body: '{{ body_FormData "document" "@/path/to/file.pdf" }}'
|
||||
|
||||
# File from URL
|
||||
body: '{{ body_FormData "image" "@https://example.com/photo.jpg" }}'
|
||||
|
||||
# Mixed text fields and files
|
||||
body: |
|
||||
{{ body_FormData
|
||||
"title" "My Report"
|
||||
"author" "John Doe"
|
||||
"cover" "@/path/to/cover.jpg"
|
||||
"document" "@/path/to/report.pdf"
|
||||
}}
|
||||
|
||||
# Multiple files with same field name
|
||||
body: |
|
||||
{{ body_FormData
|
||||
"files" "@/path/to/file1.pdf"
|
||||
"files" "@/path/to/file2.pdf"
|
||||
}}
|
||||
|
||||
# Escape @ for literal value (sends "@username")
|
||||
body: '{{ body_FormData "twitter" "@@username" }}'
|
||||
```
|
||||
|
||||
> **Note:** Files are cached in memory after the first read. Subsequent requests reuse the cached content, avoiding repeated disk/network I/O.
|
||||
|
||||
### File Functions
|
||||
|
||||
| Function | Description | Example |
|
||||
| --------------------------- | --------------------------------------------------------------------------- | ------------------------------------------ |
|
||||
| `file_Base64(source string)` | Read a file (local path or URL) and return its Base64 encoded content. Files are cached after first read. | `{{ file_Base64 "/path/to/file.pdf" }}` |
|
||||
|
||||
**`file_Base64` Details:**
|
||||
|
||||
```yaml
|
||||
# Local file as Base64 in JSON body
|
||||
body: '{"file": "{{ file_Base64 "/path/to/document.pdf" }}", "filename": "document.pdf"}'
|
||||
|
||||
# Remote file as Base64
|
||||
body: '{"image": "{{ file_Base64 "https://example.com/photo.jpg" }}"}'
|
||||
|
||||
# Combined with values for reuse
|
||||
values: "FILE_DATA={{ file_Base64 \"/path/to/file.bin\" }}"
|
||||
body: '{"data": "{{ .Values.FILE_DATA }}"}'
|
||||
```
|
||||
|
||||
## Fake Data Functions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user