or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

auto-configuration.mdheader-theme-resolution.mdindex.mdservice-theme-resolution.mdtheme-resolution.mdtheme-sources.md

header-theme-resolution.mddocs/

0

# Header-Based Theme Resolution

1

2

Simple theme resolution that extracts theme names from HTTP request headers.

3

4

## Capabilities

5

6

### RequestHeaderThemeResolver

7

8

Theme resolver that extracts theme from HTTP request headers using a configured header name.

9

10

```java { .api }

11

/**

12

* Theme resolver that extracts theme from HTTP request headers

13

*/

14

public class RequestHeaderThemeResolver extends AbstractThemeResolver {

15

16

/**

17

* Constructor with header name configuration

18

* @param themeHeaderName Name of HTTP header to check for theme value

19

*/

20

public RequestHeaderThemeResolver(String themeHeaderName);

21

22

/**

23

* Resolves theme from request header

24

* @param request HTTP request containing theme header

25

* @return Theme name from header, or default theme if header missing/empty

26

*/

27

@Nonnull

28

@Override

29

public String resolveThemeName(HttpServletRequest request);

30

31

/**

32

* No-op implementation for theme setting

33

* @param httpServletRequest HTTP request

34

* @param httpServletResponse HTTP response

35

* @param theme Theme name

36

*/

37

@Override

38

public void setThemeName(@Nonnull HttpServletRequest httpServletRequest,

39

HttpServletResponse httpServletResponse, String theme);

40

}

41

```

42

43

**Usage Examples:**

44

45

```java

46

import org.apereo.cas.services.web.RequestHeaderThemeResolver;

47

48

// Create header-based theme resolver

49

RequestHeaderThemeResolver headerResolver = new RequestHeaderThemeResolver("X-CAS-Theme");

50

headerResolver.setDefaultThemeName("default");

51

52

// Resolve theme from request

53

String themeName = headerResolver.resolveThemeName(request);

54

55

// Example HTTP request with theme header:

56

// GET /cas/login HTTP/1.1

57

// Host: cas.example.com

58

// X-CAS-Theme: dark

59

//

60

// Result: themeName = "dark"

61

```

62

63

## Header Configuration

64

65

### Standard Header Names

66

67

Common header names used for theme selection:

68

69

```java

70

// Common theme header patterns

71

new RequestHeaderThemeResolver("X-Theme"); // Generic

72

new RequestHeaderThemeResolver("X-CAS-Theme"); // CAS-specific

73

new RequestHeaderThemeResolver("X-UI-Theme"); // UI-specific

74

new RequestHeaderThemeResolver("Theme"); // Simple

75

new RequestHeaderThemeResolver("X-Client-Theme"); // Client-specific

76

```

77

78

### Custom Header Names

79

80

Any valid HTTP header name can be used:

81

82

```java

83

// Examples of custom header configurations

84

new RequestHeaderThemeResolver("X-Brand-Theme");

85

new RequestHeaderThemeResolver("X-Tenant-Theme");

86

new RequestHeaderThemeResolver("X-Mobile-Theme");

87

new RequestHeaderThemeResolver("Preferred-Theme");

88

```

89

90

## Integration Patterns

91

92

### API-Driven Theme Selection

93

94

Ideal for API clients that need to specify themes programmatically:

95

96

```http

97

POST /cas/v1/tickets HTTP/1.1

98

Host: cas.example.com

99

Content-Type: application/json

100

X-CAS-Theme: api-minimal

101

102

{

103

"username": "user@example.com",

104

"password": "secret"

105

}

106

```

107

108

### Mobile App Integration

109

110

Mobile applications can specify appropriate themes:

111

112

```http

113

GET /cas/login?service=https://mobile.example.com HTTP/1.1

114

Host: cas.example.com

115

User-Agent: MyMobileApp/1.0

116

X-CAS-Theme: mobile-dark

117

```

118

119

### Multi-Tenant Applications

120

121

Different tenants can specify their themes:

122

123

```http

124

GET /cas/login?service=https://tenant1.example.com HTTP/1.1

125

Host: cas.example.com

126

X-Tenant-Theme: tenant1-corporate

127

```

128

129

### Load Balancer Integration

130

131

Load balancers can add theme headers based on routing rules:

132

133

```nginx

134

# Nginx configuration example

135

location /cas/login {

136

proxy_pass http://cas-backend;

137

138

# Add theme header based on host

139

if ($host = "admin.example.com") {

140

proxy_set_header X-CAS-Theme "admin";

141

}

142

if ($host = "mobile.example.com") {

143

proxy_set_header X-CAS-Theme "mobile";

144

}

145

}

146

```

147

148

## Theme Resolution Behavior

149

150

### Header Processing

151

152

- **Case Sensitive**: Header names are case-sensitive

153

- **First Value**: Uses first header value if multiple headers present

154

- **Trim Whitespace**: Theme values are trimmed of leading/trailing whitespace

155

- **Empty Headers**: Empty or whitespace-only headers treated as missing

156

157

### Default Theme Fallback

158

159

Returns default theme when:

160

- Header is not present in request

161

- Header value is empty or whitespace-only

162

- Header value is null

163

164

```java

165

// Example resolution logic

166

String headerValue = request.getHeader(themeHeaderName);

167

if (StringUtils.isBlank(headerValue)) {

168

return getDefaultThemeName(); // "default"

169

}

170

return headerValue.trim();

171

```

172

173

## Security Considerations

174

175

### Header Validation

176

177

The resolver performs minimal validation:

178

- No theme name validation against available themes

179

- No sanitization of header values

180

- No protection against header injection

181

182

### Recommended Practices

183

184

1. **Theme Validation**: Validate themes exist at theme source level

185

2. **Input Sanitization**: Sanitize theme names before use

186

3. **Allowlist Themes**: Maintain allowlist of valid theme names

187

4. **Header Security**: Use secure header naming conventions

188

189

```java

190

// Example theme validation wrapper

191

public class ValidatingHeaderThemeResolver extends RequestHeaderThemeResolver {

192

private final Set<String> validThemes;

193

194

@Override

195

public String resolveThemeName(HttpServletRequest request) {

196

String theme = super.resolveThemeName(request);

197

if (validThemes.contains(theme)) {

198

return theme;

199

}

200

return getDefaultThemeName();

201

}

202

}

203

```

204

205

## Request Context Integration

206

207

### Request Attribute Storage

208

209

When used in ChainingThemeResolver, resolved themes are stored as request attributes:

210

211

```java

212

// Theme stored as request attribute for later use

213

String attributeName = casProperties.getTheme().getParamName(); // Default: "theme"

214

request.setAttribute(attributeName, resolvedTheme);

215

```

216

217

### Spring Web MVC Integration

218

219

Works seamlessly with Spring Web MVC theme resolution:

220

221

```java

222

// Spring controller can access resolved theme

223

@Controller

224

public class LoginController {

225

226

@RequestMapping("/login")

227

public String login(HttpServletRequest request, Model model) {

228

String theme = (String) request.getAttribute("theme");

229

model.addAttribute("currentTheme", theme);

230

return "login";

231

}

232

}

233

```

234

235

## Performance Characteristics

236

237

- **Very Fast**: Simple header lookup with minimal processing

238

- **No I/O**: No file system or network access required

239

- **Stateless**: No session or persistence overhead

240

- **Cache Friendly**: Results can be cached per request if needed

241

242

## Common Use Cases

243

244

1. **API Authentication**: REST clients specifying themes

245

2. **Mobile Applications**: Native apps requesting mobile-optimized themes

246

3. **Multi-Brand Platforms**: Different brands specifying their themes

247

4. **A/B Testing**: Experimental themes via header injection

248

5. **Load Balancer Routing**: Infrastructure-level theme assignment

249

6. **Development/Testing**: Easy theme switching during development