mirror of
https://github.com/aykhans/sarin.git
synced 2026-02-27 22:39:13 +00:00
Compare commits
4 Commits
d197e90103
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c299fda79d | |||
| 1f06b43b06 | |||
| e031c8e7a5 | |||
|
|
de24f9d4a4 |
@@ -10,6 +10,8 @@ Sarin supports Go templates in URL paths, methods, bodies, headers, params, cook
|
||||
- [General Functions](#general-functions)
|
||||
- [String Functions](#string-functions)
|
||||
- [Collection Functions](#collection-functions)
|
||||
- [Time Functions](#time-functions)
|
||||
- [Crypto Functions](#crypto-functions)
|
||||
- [Body Functions](#body-functions)
|
||||
- [File Functions](#file-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_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
|
||||
|
||||
| Function | Description | Example |
|
||||
@@ -153,11 +173,18 @@ body: '{{ body_FormData "twitter" "@@username" }}'
|
||||
|
||||
| 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` Details:**
|
||||
**`file_Read` and `file_Base64` Details:**
|
||||
|
||||
```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
|
||||
body: '{"file": "{{ file_Base64 "/path/to/document.pdf" }}", "filename": "document.pdf"}'
|
||||
|
||||
|
||||
2
go.mod
2
go.mod
@@ -15,7 +15,7 @@ require (
|
||||
github.com/yuin/gopher-lua v1.1.1
|
||||
go.aykhans.me/utils v1.0.7
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.3
|
||||
golang.org/x/net v0.50.0
|
||||
golang.org/x/net v0.51.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
4
go.sum
4
go.sum
@@ -111,8 +111,8 @@ go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
|
||||
@@ -2,7 +2,11 @@ package sarin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/md5" // #nosec G501 -- exposed intentionally as a template utility helper
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"math/rand/v2"
|
||||
"mime/multipart"
|
||||
"strings"
|
||||
@@ -81,7 +85,47 @@ func NewDefaultTemplateFuncMap(randSource rand.Source, fileCache *FileCache) tem
|
||||
"slice_Uint": func(values ...uint) []uint { return values },
|
||||
"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_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.
|
||||
// Usage: {{ file_Base64 "/path/to/file.pdf" }}
|
||||
// {{ file_Base64 "https://example.com/image.png" }}
|
||||
|
||||
Reference in New Issue
Block a user