Data Validation
Ductape lets you define validation rules for Action inputs, ensuring data consistency and integrity before requests are sent.
Overview
When you import Actions, Ductape automatically detects input parameters from the request body, query strings, headers, and route parameters. You can then configure validation rules to:
- Enforce required fields
- Set minimum and maximum lengths
- Define data types
- Provide default values
- Add decorators for display formatting
Prerequisites
Before configuring validation, ensure you have:
- The Ductape SDK installed and initialized
- An App with imported Actions
- TypeScript
- Java
- Go
- .NET
import Ductape from '@ductape/sdk';
const ductape = new Ductape({
accessKey: 'your-access-key',
});
import app.ductape.sdk.Ductape;
import app.ductape.sdk.core.EnvType;
import app.ductape.sdk.core.RequestContext;
RequestContext auth = new RequestContext(null, null, null, null, 'your-access-key');
Ductape ductape = new Ductape(EnvType.PRODUCTION, auth);
import (
"context"
"github.com/ductape/ductape/sdk/go/core"
ductapesdk "github.com/ductape/ductape/sdk/go/ductape"
)
auth := core.NewRequestContext("", "", "", "", 'your-access-key')
client, err := ductapesdk.New(core.EnvProduction, auth)
if err != nil {
return err
}
using Ductape.Sdk;
using Ductape.Sdk.Core;
var auth = new RequestContext(null, null, null, null, 'your-access-key', null);
var ductape = new Ductape(EnvType.Production, auth);
Validation Properties
| Field | Type | Description |
|---|---|---|
description | string | Explanation of the field's purpose |
required | boolean | Whether the field is mandatory |
maxLength | number | Maximum allowed length for strings |
minLength | number | Minimum allowed length for strings |
decorator | string | Text or symbol displayed alongside the value |
decoratorPosition | DecoratorPositions | Position of the decorator (PREPEND, APPEND, or UNSET) |
type | DataTypes | The expected data type |
defaultValue | string | number | boolean | Default value if none is provided |
sampleValue | string | number | object | Example demonstrating expected format |
Selector Format
To update validation, you need to specify which field you're targeting using a selector string:
| Selector | Target |
|---|---|
$Body{action_tag}{...}{key} | Request body fields |
$Query{action_tag}{...}{key} | URL query parameters |
$Params{action_tag}{...}{key} | Route parameters |
$Header{action_tag}{...}{key} | HTTP headers |
Nested Fields
For nested objects, chain the keys:
$Body{createUser}{user}{profile}{firstName}
This targets body.user.profile.firstName in the createUser Action.
Updating Validation Rules
Use ductape.apps.validation() to set validation rules:
- TypeScript
- Java
- Go
- .NET
await ductape.apps.validation(selector, validationRules);
ductape.apps.validation(selector, validationRules);
client.apps.validation(selector, validationRules);
await ductape.apps.validation(selector, validationRules);
Example: Username Validation
- TypeScript
- Java
- Go
- .NET
await ductape.apps.validation('$Body{createUser}{user}{username}', {
description: 'Username for the new account',
required: true,
type: 'nospaces_string',
maxLength: 30,
minLength: 3,
defaultValue: '',
});
ductape.apps.validation('$BodyMap.of(createUser)Map.of(user)Map.of(username)', Map.of(
"description", "Username for the new account",
"required", true,
"type", "nospaces_string",
"maxLength", 30,
"minLength", 3,
"defaultValue", ""
));
client.apps.validation('$Body{createUser}{user}{username}', {
"description": "Username for the new account",
"required": true,
"type": "nospaces_string",
"maxLength": 30,
"minLength": 3,
"defaultValue": "",
});
await ductape.apps.validation('$Body{createUser}{user}{username}', {
["description"] = "Username for the new account",
["required"] = true,
["type"] = "nospaces_string",
["maxLength"] = 30,
["minLength"] = 3,
["defaultValue"] = "",
});
Example: Price Field with Decorator
- TypeScript
- Java
- Go
- .NET
import { DecoratorPositions } from '@ductape/sdk/types';
await ductape.apps.validation('$Body{createProduct}{product}{price}', {
description: 'Price of the product in USD',
required: true,
type: 'float',
decorator: '$',
decoratorPosition: DecoratorPositions.PREPEND,
defaultValue: 0.0,
});
ductape.apps.validation('$BodyMap.of(createProduct)Map.of(product)Map.of(price)', Map.of(
"description", "Price of the product in USD",
"required", true,
"type", "float",
"decorator", "$",
decoratorPosition: DecoratorPositions.PREPEND,
"defaultValue", 0.0
));
client.apps.validation('$Body{createProduct}{product}{price}', {
"description": "Price of the product in USD",
"required": true,
"type": "float",
"decorator": "$",
decoratorPosition: DecoratorPositions.PREPEND,
"defaultValue": 0.0,
});
await ductape.apps.validation('$Body{createProduct}{product}{price}', {
["description"] = "Price of the product in USD",
["required"] = true,
["type"] = "float",
["decorator"] = "$",
decoratorPosition: DecoratorPositions.PREPEND,
["defaultValue"] = 0.0,
});
Example: Array of Tags
- TypeScript
- Java
- Go
- .NET
await ductape.apps.validation('$Body{createBlogPost}{post}{tags}', {
description: 'Tags associated with the blog post',
type: 'array-string',
defaultValue: [],
});
ductape.apps.validation('$BodyMap.of(createBlogPost)Map.of(post)Map.of(tags)', Map.of(
"description", "Tags associated with the blog post",
"type", "array-string",
defaultValue: []
));
client.apps.validation('$Body{createBlogPost}{post}{tags}', {
"description": "Tags associated with the blog post",
"type": "array-string",
defaultValue: [],
});
await ductape.apps.validation('$Body{createBlogPost}{post}{tags}', {
["description"] = "Tags associated with the blog post",
["type"] = "array-string",
defaultValue: [],
});
Example: Required UUID Parameter
- TypeScript
- Java
- Go
- .NET
await ductape.apps.validation('$Params{getUser}{id}', {
type: 'uuid',
required: true,
description: 'Unique identifier for the user',
});
ductape.apps.validation('$ParamsMap.of(getUser)Map.of(id)', Map.of(
"type", "uuid",
"required", true,
"description", "Unique identifier for the user"
));
client.apps.validation('$Params{getUser}{id}', {
"type": "uuid",
"required": true,
"description": "Unique identifier for the user",
});
await ductape.apps.validation('$Params{getUser}{id}', {
["type"] = "uuid",
["required"] = true,
["description"] = "Unique identifier for the user",
});
Data Types
| Type | Value | Description | Example |
|---|---|---|---|
| STRING | "string" | General string | "Hello World" |
| NOSPACES_STRING | "nospaces_string" | String without spaces | "NoSpaces" |
| EMAIL_STRING | "email_string" | Valid email format | "user@example.com" |
| NUMBER_STRING | "numberstring" | Number in string format | "12345" |
| INTEGER | "number" | Whole number | 42 |
| FLOAT | "float" | Floating-point number | 3.14 |
| DOUBLE | "double" | Double-precision number | 123.456789 |
| UUID | "uuid" | UUID format | "550e8400-e29b-41d4..." |
| ARRAY | "array" | General array | [1, "text", true] |
| OBJECT | "object" | Object structure | { key: "value" } |
| BOOLEAN | "boolean" | Boolean value | true |
| STRING_ARRAY | "array-string" | Array of strings | ["apple", "banana"] |
| INTEGER_ARRAY | "array-number" | Array of integers | [1, 2, 3] |
| FLOAT_ARRAY | "array-float" | Array of floats | [1.1, 2.2, 3.3] |
| DOUBLE_ARRAY | "array-double" | Array of doubles | [1.123456, 2.654321] |
| UUID_ARRAY | "array-uuid" | Array of UUIDs | ["550e8400-..."] |
| BOOLEAN_ARRAY | "array-boolean" | Array of booleans | [true, false] |
Decorator Positions
| Position | Value | Description | Example |
|---|---|---|---|
| PREPEND | "BEFORE" | Decorator appears before value | $100 |
| APPEND | "AFTER" | Decorator appears after value | 100$ |
| UNSET | "" | No decorator | 100 |
Complete Example
Here's a complete example setting up validation for a user registration Action:
- TypeScript
- Java
- Go
- .NET
import Ductape from '@ductape/sdk';
import { DecoratorPositions } from '@ductape/sdk/types';
async function setupValidation() {
const ductape = new Ductape({
accessKey: 'your-access-key',
});
// Username validation
await ductape.apps.validation('$Body{registerUser}{username}', {
description: 'Unique username for the account',
required: true,
type: 'nospaces_string',
minLength: 3,
maxLength: 20,
});
// Email validation
await ductape.apps.validation('$Body{registerUser}{email}', {
description: 'Email address for account verification',
required: true,
type: 'email_string',
});
// Age validation
await ductape.apps.validation('$Body{registerUser}{age}', {
description: 'User age (must be 18 or older)',
required: false,
type: 'number',
defaultValue: 18,
});
// Roles validation
await ductape.apps.validation('$Body{registerUser}{roles}', {
description: 'User roles for access control',
required: false,
type: 'array-string',
defaultValue: ['user'],
});
console.log('Validation rules configured successfully');
}
setupValidation().catch(console.error);
import app.ductape.sdk.Ductape;
import app.ductape.sdk.core.EnvType;
import app.ductape.sdk.core.RequestContext;
async function setupValidation() Map.of(
RequestContext auth = new RequestContext(null, null, null, null, 'your-access-key');
Ductape ductape = new Ductape(EnvType.PRODUCTION, auth);
// Username validation
ductape.apps.validation('$BodyMap.of(registerUser)Map.of(username)', Map.of(
"description", "Unique username for the account",
"required", true,
"type", "nospaces_string",
"minLength", 3,
"maxLength", 20
));
// Email validation
ductape.apps.validation('$BodyMap.of(registerUser)Map.of(email)', Map.of(
"description", "Email address for account verification",
"required", true,
"type", "email_string"
));
// Age validation
ductape.apps.validation('$BodyMap.of(registerUser)Map.of(age)', Map.of(
"description", "User age (must be 18 or older)",
"required", false,
"type", "number",
"defaultValue", 18
));
// Roles validation
ductape.apps.validation('$BodyMap.of(registerUser)Map.of(roles)', Map.of(
"description", "User roles for access control",
"required", false,
"type", "array-string",
defaultValue: ['user']
));
System.out.println('Validation rules configured successfully');
)
setupValidation();
import (
"context"
"github.com/ductape/ductape/sdk/go/core"
ductapesdk "github.com/ductape/ductape/sdk/go/ductape"
)
async function setupValidation() {
auth := core.NewRequestContext("", "", "", "", 'your-access-key')
client, err := ductapesdk.New(core.EnvProduction, auth)
if err != nil {
return err
}
// Username validation
client.apps.validation('$Body{registerUser}{username}', {
"description": "Unique username for the account",
"required": true,
"type": "nospaces_string",
"minLength": 3,
"maxLength": 20,
});
// Email validation
client.apps.validation('$Body{registerUser}{email}', {
"description": "Email address for account verification",
"required": true,
"type": "email_string",
});
// Age validation
client.apps.validation('$Body{registerUser}{age}', {
"description": "User age (must be 18 or older)",
"required": false,
"type": "number",
"defaultValue": 18,
});
// Roles validation
client.apps.validation('$Body{registerUser}{roles}', {
"description": "User roles for access control",
"required": false,
"type": "array-string",
defaultValue: ['user'],
});
fmt.Println('Validation rules configured successfully');
}
setupValidation().catch(console.error);
using Ductape.Sdk;
using Ductape.Sdk.Core;
async function setupValidation() {
var auth = new RequestContext(null, null, null, null, 'your-access-key', null);
var ductape = new Ductape(EnvType.Production, auth);
// Username validation
await ductape.apps.validation('$Body{registerUser}{username}', {
["description"] = "Unique username for the account",
["required"] = true,
["type"] = "nospaces_string",
["minLength"] = 3,
["maxLength"] = 20,
});
// Email validation
await ductape.apps.validation('$Body{registerUser}{email}', {
["description"] = "Email address for account verification",
["required"] = true,
["type"] = "email_string",
});
// Age validation
await ductape.apps.validation('$Body{registerUser}{age}', {
["description"] = "User age (must be 18 or older)",
["required"] = false,
["type"] = "number",
["defaultValue"] = 18,
});
// Roles validation
await ductape.apps.validation('$Body{registerUser}{roles}', {
["description"] = "User roles for access control",
["required"] = false,
["type"] = "array-string",
defaultValue: ['user'],
});
Console.WriteLine('Validation rules configured successfully');
}
setupValidation().catch(console.error);
Best Practices
Use Meaningful Descriptions
- TypeScript
- Java
- Go
- .NET
// Good
await ductape.apps.validation('$Body{createOrder}{total}', {
description: 'Total order amount including tax and shipping',
});
// Avoid
await ductape.apps.validation('$Body{createOrder}{total}', {
description: 'Total', // Too vague
});
// Good
ductape.apps.validation('$BodyMap.of(createOrder)Map.of(total)', Map.of(
"description", "Total order amount including tax and shipping"
));
// Avoid
ductape.apps.validation('$BodyMap.of(createOrder)Map.of(total)', Map.of(
"description", "Total", // Too vague
));
// Good
client.apps.validation('$Body{createOrder}{total}', {
"description": "Total order amount including tax and shipping",
});
// Avoid
client.apps.validation('$Body{createOrder}{total}', {
"description": "Total", // Too vague
});
// Good
await ductape.apps.validation('$Body{createOrder}{total}', {
["description"] = "Total order amount including tax and shipping",
});
// Avoid
await ductape.apps.validation('$Body{createOrder}{total}', {
["description"] = "Total", // Too vague
});
Set Appropriate Constraints
- TypeScript
- Java
- Go
- .NET
// Prevent data overflow
await ductape.apps.validation('$Body{createPost}{title}', {
maxLength: 200,
minLength: 1,
required: true,
});
// Prevent data overflow
ductape.apps.validation('$BodyMap.of(createPost)Map.of(title)', Map.of(
"maxLength", 200,
"minLength", 1,
"required", true
));
// Prevent data overflow
client.apps.validation('$Body{createPost}{title}', {
"maxLength": 200,
"minLength": 1,
"required": true,
});
// Prevent data overflow
await ductape.apps.validation('$Body{createPost}{title}', {
["maxLength"] = 200,
["minLength"] = 1,
["required"] = true,
});
Use Default Values for Optional Fields
- TypeScript
- Java
- Go
- .NET
await ductape.apps.validation('$Body{createUser}{status}', {
required: false,
defaultValue: 'pending',
});
ductape.apps.validation('$BodyMap.of(createUser)Map.of(status)', Map.of(
"required", false,
"defaultValue", "pending"
));
client.apps.validation('$Body{createUser}{status}', {
"required": false,
"defaultValue": "pending",
});
await ductape.apps.validation('$Body{createUser}{status}', {
["required"] = false,
["defaultValue"] = "pending",
});
Choose the Correct Data Type
- TypeScript
- Java
- Go
- .NET
// Use specific types for better validation
await ductape.apps.validation('$Body{sendEmail}{to}', {
type: 'email_string', // Not just 'string'
required: true,
});
// Use specific types for better validation
ductape.apps.validation('$BodyMap.of(sendEmail)Map.of(to)', Map.of(
"type", "email_string", // Not just 'string'
"required", true
));
// Use specific types for better validation
client.apps.validation('$Body{sendEmail}{to}', {
"type": "email_string", // Not just 'string'
"required": true,
});
// Use specific types for better validation
await ductape.apps.validation('$Body{sendEmail}{to}', {
["type"] = "email_string", // Not just 'string'
["required"] = true,
});
Next Steps
- Running Actions - Execute Actions with validated inputs
- Managing Actions - Update Action configuration
- Actions Overview - Return to Actions overview
See Also
- Getting Started with Apps - Create and configure Apps
- Constants & Variables - Dynamic configuration values