LogoRevali

Implied Binding

Types that don't need binding annotations

Some types are automatically detected by Revali and don't require binding annotations. This makes your code cleaner and reduces boilerplate.

What Is Implied Binding?#

Implied binding means Revali automatically knows how to provide certain types to your endpoints and controllers without explicit annotations. You can use these types directly as parameters.

Request/Response Objects#

Response Objects#

@Controller('api')
class ApiController {
  @Get('custom')
  String getCustom(Headers headers) {
    headers['X-Custom-Header'] = 'My Value';
    return 'Custom response';
  }
}
TypePurposeWhen to Use
Headers or ResponseHeaders Read & Modify response headers Manage response headers
Cookies or ResponseCookies Read & Modify response cookies Manage response cookies
SetCookiesSet response cookiesSetting custom cookies
ResponseFull response controlAdvanced response handling

Request Objects#

@Controller('api')
class ApiController {
  @Get('debug')
  String debug(Request request) {
    return 'Method: ${request.method}, Path: ${request.path}';
  }
}
TypePurposeWhen to Use
RequestRead request dataDebugging, logging
RequestHeadersRead request headersHeader inspection
RequestCookiesRead request cookiesCookie inspection

For the client IP only, prefer @Ip() instead of reading request.ip manually.

Context Providers#

These types provide access to request context and metadata:

Available Context Types#

TypePurposeUse Case
DI Dependency Injection container Access all registered dependencies
Meta Request metadata Read/write request metadata
MetaScope Request metadata scope Access metadata with scope context
RouteEntry Route information Access current route details
Context Full request context Access complete request context
Data Data sharing between components Share data across middleware/guards/endpoints
CleanUp Resource cleanup Register cleanup functions
ReflectHandler Reflection utilities Access reflection capabilities

Best Practices#

Use Implied Types When Appropriate#

// ✅ Good - using implied binding for context
@Controller('api')
class ApiController {
  @Get('status')
  String getStatus(Meta meta) {
    return 'Request to ${meta.request.path} at ${DateTime.now()}';
  }
}

// ✅ Good - using binding for data extraction
@Controller('users')
class UsersController {
  @Get(':id')
  String getUser(@Param() String id) {
    return 'User ID: $id';
  }
}

Avoid Overusing Low-Level Types#

// ❌ Avoid - too much low-level access
@Controller('api')
class ApiController {
  @Get('data')
  String getData(
    Request request,
    ReadOnlyHeaders headers,
    ReadOnlyBody body,
    MutableResponse response,
  ) {
    // Too much manual work!
  }
}

// ✅ Better - use bindings and pipes
@Controller('api')
class ApiController {
  @Get('data')
  String getData(
    @Body() MyData data,
    @Header('Authorization') String? auth,
  ) {
    // Clean and testable
  }
}

Combine Implied and Explicit Binding#

@Controller('users')
class UsersController {
  @Get('profile')
  String getProfile(
    @Param() String id,           // Explicit binding
    Data data,            // Implied binding
    @Dep() UserService service,   // Explicit binding
  ) {
    final currentUser = data.get<User>('currentUser');
    return service.getUserProfile(id, currentUser);
  }
}

What's Next?#

Now that you understand implied binding, you have a complete picture of Revali's data handling:

  1. Binding - Extract data with annotations
  2. Pipes - Transform and validate data
  3. HTTP Methods - Define endpoint behavior and path parameters
  4. Controllers - Organize your endpoints