or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cors-extension.mdcross-origin-decorator.mdindex.md

cross-origin-decorator.mddocs/

0

# Cross-Origin Decorator

1

2

The `cross_origin` decorator provides route-specific Cross-Origin Resource Sharing configuration for individual Flask routes. It offers fine-grained control over CORS settings on a per-route basis with automatic OPTIONS request handling.

3

4

## Capabilities

5

6

### Cross-Origin Decorator Function

7

8

Decorator function that wraps Flask route handlers to enable CORS with configurable parameters. Applied directly to route functions for granular CORS control.

9

10

```python { .api }

11

def cross_origin(

12

origins="*",

13

methods=None,

14

expose_headers=None,

15

allow_headers="*",

16

supports_credentials=False,

17

max_age=None,

18

send_wildcard=False,

19

vary_header=True,

20

automatic_options=True,

21

allow_private_network=False,

22

always_send=True,

23

**kwargs

24

):

25

"""

26

Decorator to enable CORS for specific Flask routes.

27

28

Parameters:

29

- origins: Allowed origins (string, list, or regex patterns)

30

- methods: Allowed HTTP methods (list or string)

31

- expose_headers: Headers safe to expose to CORS API (list or string)

32

- allow_headers: Headers allowed in requests (list, string, or regex)

33

- supports_credentials: Allow authenticated requests (bool)

34

- max_age: Cache time for preflight requests (timedelta, int, or string)

35

- send_wildcard: Send '*' instead of specific origin (bool)

36

- vary_header: Include Vary: Origin header (bool)

37

- automatic_options: Handle OPTIONS requests automatically (bool)

38

- allow_private_network: Allow private network access (bool, default: False)

39

- always_send: Send CORS headers even without Origin header (bool)

40

- **kwargs: Additional configuration options

41

42

Returns:

43

Decorated function with CORS headers applied

44

"""

45

```

46

47

## Usage Examples

48

49

### Basic Route Decoration

50

51

```python

52

from flask import Flask

53

from flask_cors import cross_origin

54

55

app = Flask(__name__)

56

57

@app.route("/api/data")

58

@cross_origin() # Allow all origins with default settings

59

def get_data():

60

return {"message": "CORS-enabled data"}

61

62

@app.route("/api/public")

63

@cross_origin(origins="*") # Explicit wildcard

64

def public_endpoint():

65

return {"data": "public information"}

66

```

67

68

### Specific Origins

69

70

```python

71

from flask import Flask

72

from flask_cors import cross_origin

73

74

app = Flask(__name__)

75

76

@app.route("/api/secure")

77

@cross_origin(origins=["https://trusted-site.com", "https://app.example.com"])

78

def secure_endpoint():

79

return {"data": "restricted data"}

80

81

@app.route("/api/development")

82

@cross_origin(origins=["http://localhost:3000", "http://localhost:8080"])

83

def development_endpoint():

84

return {"data": "development data"}

85

```

86

87

### Regex Origins

88

89

```python

90

import re

91

from flask import Flask

92

from flask_cors import cross_origin

93

94

app = Flask(__name__)

95

96

@app.route("/api/subdomains")

97

@cross_origin(origins=r"https://.*\.example\.com")

98

def subdomain_endpoint():

99

return {"data": "subdomain accessible"}

100

101

@app.route("/api/pattern")

102

@cross_origin(origins=[

103

re.compile(r"https://app\d+\.example\.com"),

104

"https://main.example.com"

105

])

106

def pattern_endpoint():

107

return {"data": "pattern matched"}

108

```

109

110

### Method-Specific CORS

111

112

```python

113

from flask import Flask, request

114

from flask_cors import cross_origin

115

116

app = Flask(__name__)

117

118

@app.route("/api/users", methods=["GET", "POST"])

119

@cross_origin(

120

origins=["https://frontend.example.com"],

121

methods=["GET", "POST"],

122

allow_headers=["Content-Type", "X-Requested-With"]

123

)

124

def users_endpoint():

125

if request.method == "GET":

126

return {"users": []}

127

elif request.method == "POST":

128

return {"created": True}

129

```

130

131

### Credentials Support

132

133

```python

134

from flask import Flask

135

from flask_cors import cross_origin

136

137

app = Flask(__name__)

138

139

@app.route("/api/auth/profile")

140

@cross_origin(

141

origins=["https://app.example.com"],

142

supports_credentials=True,

143

allow_headers=["Content-Type", "Authorization"]

144

)

145

def user_profile():

146

# This route accepts cookies and credentials

147

return {"profile": "user data"}

148

149

@app.route("/api/auth/login", methods=["POST"])

150

@cross_origin(

151

origins=["https://app.example.com"],

152

supports_credentials=True,

153

methods=["POST"]

154

)

155

def login():

156

return {"token": "auth-token"}

157

```

158

159

### Custom Headers Configuration

160

161

```python

162

from flask import Flask

163

from flask_cors import cross_origin

164

165

app = Flask(__name__)

166

167

@app.route("/api/upload", methods=["POST"])

168

@cross_origin(

169

origins=["https://uploader.example.com"],

170

allow_headers=["Content-Type", "X-File-Name", "X-Upload-Key"],

171

expose_headers=["X-Upload-ID", "X-Processing-Status"],

172

methods=["POST", "OPTIONS"]

173

)

174

def file_upload():

175

return {"upload_id": "12345", "status": "processing"}

176

```

177

178

### Preflight Caching

179

180

```python

181

from datetime import timedelta

182

from flask import Flask

183

from flask_cors import cross_origin

184

185

app = Flask(__name__)

186

187

@app.route("/api/heavy-operation", methods=["POST"])

188

@cross_origin(

189

origins=["https://client.example.com"],

190

max_age=timedelta(hours=1), # Cache preflight for 1 hour

191

methods=["POST"]

192

)

193

def heavy_operation():

194

# Expensive operation that benefits from preflight caching

195

return {"result": "computed"}

196

197

@app.route("/api/frequent-calls")

198

@cross_origin(

199

origins=["https://dashboard.example.com"],

200

max_age=3600, # Cache for 1 hour (seconds)

201

allow_headers=["Content-Type", "Authorization"]

202

)

203

def frequent_endpoint():

204

return {"data": "frequently accessed"}

205

```

206

207

### OPTIONS Handling Control

208

209

```python

210

from flask import Flask, jsonify

211

from flask_cors import cross_origin

212

213

app = Flask(__name__)

214

215

@app.route("/api/custom-options", methods=["GET", "POST", "OPTIONS"])

216

@cross_origin(

217

origins=["https://custom.example.com"],

218

automatic_options=False # Handle OPTIONS manually

219

)

220

def custom_options_endpoint():

221

if request.method == "OPTIONS":

222

# Custom preflight response

223

return jsonify({"preflight": "custom response"})

224

elif request.method == "GET":

225

return {"data": "get response"}

226

elif request.method == "POST":

227

return {"data": "post response"}

228

```

229

230

### Mixed Configuration

231

232

```python

233

from flask import Flask

234

from flask_cors import cross_origin

235

236

app = Flask(__name__)

237

238

@app.route("/api/complex")

239

@cross_origin(

240

origins=[

241

"https://prod.example.com", # Production

242

"https://staging.example.com", # Staging

243

r"https://.*\.dev\.example\.com", # Development subdomains

244

"http://localhost:3000" # Local development

245

],

246

methods=["GET", "POST", "PUT", "DELETE"],

247

allow_headers=[

248

"Content-Type",

249

"Authorization",

250

"X-API-Key",

251

r"X-Custom-.*" # Regex pattern for custom headers

252

],

253

expose_headers=["X-Total-Count", "X-Rate-Limit-Remaining"],

254

supports_credentials=True,

255

max_age=1800, # 30 minutes

256

vary_header=True

257

)

258

def complex_endpoint():

259

return {"data": "complex CORS configuration"}

260

```

261

262

## Integration with Flask Extensions

263

264

The cross_origin decorator works seamlessly with other Flask extensions:

265

266

### Flask-Login Integration

267

268

```python

269

from flask import Flask

270

from flask_login import login_required

271

from flask_cors import cross_origin

272

273

app = Flask(__name__)

274

275

@app.route("/api/protected")

276

@cross_origin(

277

origins=["https://app.example.com"],

278

supports_credentials=True

279

)

280

@login_required

281

def protected_endpoint():

282

return {"data": "protected resource"}

283

```

284

285

### Flask-RESTful Integration

286

287

```python

288

from flask import Flask

289

from flask_restful import Api, Resource

290

from flask_cors import cross_origin

291

292

app = Flask(__name__)

293

api = Api(app)

294

295

class UserResource(Resource):

296

@cross_origin(origins=["https://api-client.example.com"])

297

def get(self, user_id):

298

return {"user_id": user_id}

299

300

@cross_origin(

301

origins=["https://admin.example.com"],

302

methods=["POST"],

303

supports_credentials=True

304

)

305

def post(self):

306

return {"created": True}

307

308

api.add_resource(UserResource, "/api/users/<int:user_id>")

309

```

310

311

## Error Handling

312

313

The decorator provides automatic error handling for common CORS scenarios:

314

315

- **Origin Rejection**: Non-matching origins receive responses without CORS headers

316

- **Method Validation**: Unsupported methods in preflight requests are rejected

317

- **Header Validation**: Invalid headers in preflight requests are filtered

318

- **Credential Conflicts**: Automatic validation prevents wildcard origins with credentials

319

320

## Performance Considerations

321

322

- **Decorator Overhead**: Minimal performance impact per request

323

- **Options Caching**: Use `max_age` for frequently preflight-checked endpoints

324

- **Header Processing**: Only specified headers are processed and validated

325

- **Origin Matching**: Regex patterns are compiled once at decoration time