mirror of
https://github.com/aykhans/sarin.git
synced 2026-02-28 23:09:13 +00:00
Compare commits
2 Commits
e031c8e7a5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c299fda79d | |||
| 1f06b43b06 |
@@ -10,6 +10,8 @@ Sarin supports Go templates in URL paths, methods, bodies, headers, params, cook
|
|||||||
- [General Functions](#general-functions)
|
- [General Functions](#general-functions)
|
||||||
- [String Functions](#string-functions)
|
- [String Functions](#string-functions)
|
||||||
- [Collection Functions](#collection-functions)
|
- [Collection Functions](#collection-functions)
|
||||||
|
- [Time Functions](#time-functions)
|
||||||
|
- [Crypto Functions](#crypto-functions)
|
||||||
- [Body Functions](#body-functions)
|
- [Body Functions](#body-functions)
|
||||||
- [File Functions](#file-functions)
|
- [File Functions](#file-functions)
|
||||||
- [Fake Data Functions](#fake-data-functions)
|
- [Fake Data Functions](#fake-data-functions)
|
||||||
@@ -109,6 +111,24 @@ sarin -U http://example.com/users \
|
|||||||
| `slice_Int(values ...int)` | Create int slice | `{{ slice_Int 1 2 3 }}` |
|
| `slice_Int(values ...int)` | Create int slice | `{{ slice_Int 1 2 3 }}` |
|
||||||
| `slice_Uint(values ...uint)` | Create uint slice | `{{ slice_Uint 1 2 3 }}` |
|
| `slice_Uint(values ...uint)` | Create uint slice | `{{ slice_Uint 1 2 3 }}` |
|
||||||
|
|
||||||
|
### Time Functions
|
||||||
|
|
||||||
|
| Function | Description | Example |
|
||||||
|
| ------------------------ | ------------------------------------------- | ------------------------------------------------------------------------------- |
|
||||||
|
| `time_NowUnix` | Current Unix timestamp (seconds) | `{{ time_NowUnix }}` → `1735689600` |
|
||||||
|
| `time_NowUnixMilli` | Current Unix timestamp (milliseconds) | `{{ time_NowUnixMilli }}` → `1735689600123` |
|
||||||
|
| `time_NowRFC3339` | Current time in RFC3339 format | `{{ time_NowRFC3339 }}` → `"2026-02-26T21:00:00Z"` |
|
||||||
|
| `time_Format(layout, t)` | Format a `time.Time` value with a Go layout | `{{ time_Format "2006-01-02" (strings_ToDate "2024-05-10") }}` → `"2024-05-10"` |
|
||||||
|
|
||||||
|
### Crypto Functions
|
||||||
|
|
||||||
|
| Function | Description | Example |
|
||||||
|
| ------------------------------------ | ------------------------------------------ | -------------------------------------------- |
|
||||||
|
| `crypto_SHA256(s string)` | SHA-256 hash (hex-encoded) | `{{ crypto_SHA256 "hello" }}` |
|
||||||
|
| `crypto_MD5(s string)` | MD5 hash (hex-encoded) | `{{ crypto_MD5 "hello" }}` |
|
||||||
|
| `crypto_HMACSHA256(key, msg string)` | HMAC-SHA256 signature (hex-encoded) | `{{ crypto_HMACSHA256 "secret" "payload" }}` |
|
||||||
|
| `crypto_Base64URL(s string)` | Base64 URL-safe encoding (without padding) | `{{ crypto_Base64URL "hello world" }}` |
|
||||||
|
|
||||||
### Body Functions
|
### Body Functions
|
||||||
|
|
||||||
| Function | Description | Example |
|
| Function | Description | Example |
|
||||||
@@ -153,11 +173,18 @@ body: '{{ body_FormData "twitter" "@@username" }}'
|
|||||||
|
|
||||||
| Function | Description | Example |
|
| Function | Description | Example |
|
||||||
| ---------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------- |
|
| ---------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------- |
|
||||||
|
| `file_Read(source string)` | Read a file (local path or URL) and return raw content as string. Files are cached after first read. | `{{ file_Read "/path/to/file.txt" }}` |
|
||||||
| `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(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:**
|
**`file_Read` and `file_Base64` Details:**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
# Local file as plain text
|
||||||
|
body: '{{ file_Read "/path/to/template.json" }}'
|
||||||
|
|
||||||
|
# Remote text file
|
||||||
|
body: '{{ file_Read "https://example.com/payload.txt" }}'
|
||||||
|
|
||||||
# Local file as Base64 in JSON body
|
# Local file as Base64 in JSON body
|
||||||
body: '{"file": "{{ file_Base64 "/path/to/document.pdf" }}", "filename": "document.pdf"}'
|
body: '{"file": "{{ file_Base64 "/path/to/document.pdf" }}", "filename": "document.pdf"}'
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ package sarin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/md5" // #nosec G501 -- exposed intentionally as a template utility helper
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -81,7 +85,47 @@ func NewDefaultTemplateFuncMap(randSource rand.Source, fileCache *FileCache) tem
|
|||||||
"slice_Uint": func(values ...uint) []uint { return values },
|
"slice_Uint": func(values ...uint) []uint { return values },
|
||||||
"slice_Join": strings.Join,
|
"slice_Join": strings.Join,
|
||||||
|
|
||||||
|
// Time
|
||||||
|
"time_NowUnix": func() int64 { return time.Now().Unix() },
|
||||||
|
"time_NowUnixMilli": func() int64 { return time.Now().UnixMilli() },
|
||||||
|
"time_NowRFC3339": func() string { return time.Now().Format(time.RFC3339) },
|
||||||
|
"time_Format": func(layout string, t time.Time) string {
|
||||||
|
return t.Format(layout)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Crypto
|
||||||
|
"crypto_SHA256": func(s string) string {
|
||||||
|
sum := sha256.Sum256([]byte(s))
|
||||||
|
return hex.EncodeToString(sum[:])
|
||||||
|
},
|
||||||
|
"crypto_MD5": func(s string) string {
|
||||||
|
sum := md5.Sum([]byte(s)) // #nosec G401 -- MD5 is intentionally provided as a non-security template helper
|
||||||
|
return hex.EncodeToString(sum[:])
|
||||||
|
},
|
||||||
|
"crypto_HMACSHA256": func(key string, msg string) string {
|
||||||
|
mac := hmac.New(sha256.New, []byte(key))
|
||||||
|
_, _ = mac.Write([]byte(msg))
|
||||||
|
return hex.EncodeToString(mac.Sum(nil))
|
||||||
|
},
|
||||||
|
"crypto_Base64URL": func(s string) string {
|
||||||
|
return base64.RawURLEncoding.EncodeToString([]byte(s))
|
||||||
|
},
|
||||||
|
|
||||||
// File
|
// File
|
||||||
|
// file_Read reads a file (local or remote URL) and returns its content as a string.
|
||||||
|
// Usage: {{ file_Read "/path/to/file.txt" }}
|
||||||
|
// {{ file_Read "https://example.com/data.txt" }}
|
||||||
|
"file_Read": func(source string) (string, error) {
|
||||||
|
if fileCache == nil {
|
||||||
|
return "", types.ErrFileCacheNotInitialized
|
||||||
|
}
|
||||||
|
cached, err := fileCache.GetOrLoad(source)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(cached.Content), nil
|
||||||
|
},
|
||||||
|
|
||||||
// file_Base64 reads a file (local or remote URL) and returns its Base64 encoded content.
|
// file_Base64 reads a file (local or remote URL) and returns its Base64 encoded content.
|
||||||
// Usage: {{ file_Base64 "/path/to/file.pdf" }}
|
// Usage: {{ file_Base64 "/path/to/file.pdf" }}
|
||||||
// {{ file_Base64 "https://example.com/image.png" }}
|
// {{ file_Base64 "https://example.com/image.png" }}
|
||||||
|
|||||||
Reference in New Issue
Block a user