or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

event-adapter.mdevent-handling.mdindex.mdserver-integration.md

server-integration.mddocs/

0

# Server Integration

1

2

Integration capabilities for incorporating Slack event handling into existing Flask applications, Blueprints, and other WSGI-compatible web frameworks. The SlackServer class handles HTTP request processing, signature verification, and Slack-specific protocol requirements.

3

4

## Capabilities

5

6

### SlackServer Internal Implementation

7

8

Internal Flask server that processes HTTP requests and handles Slack Events API protocol requirements.

9

10

```python { .api }

11

class SlackServer(Flask):

12

def __init__(self, signing_secret, endpoint, emitter, server):

13

"""

14

Internal server for handling Slack Events API requests.

15

16

Parameters:

17

- signing_secret: str - Slack app's signing secret

18

- endpoint: str - URL endpoint for receiving events

19

- emitter: SlackEventAdapter - Event emitter instance

20

- server: Flask/Blueprint/LocalProxy or None - Server to bind to

21

22

Raises:

23

- TypeError: If server is not Flask, Blueprint, or LocalProxy instance

24

"""

25

```

26

27

### Route Binding

28

29

Binds the Slack event handling route to existing Flask applications or Blueprints.

30

31

```python { .api }

32

def bind_route(self, server):

33

"""

34

Bind the event handling route to a Flask server or Blueprint.

35

36

Parameters:

37

- server: Flask/Blueprint/LocalProxy - Server instance to bind route to

38

39

Returns:

40

None

41

"""

42

```

43

44

### Signature Verification

45

46

Verifies incoming request signatures using HMAC-SHA256 to ensure requests are from Slack.

47

48

```python { .api }

49

def verify_signature(self, timestamp: str, signature: str) -> bool:

50

"""

51

Verify the request signature using the app's signing secret.

52

53

Parameters:

54

- timestamp: str - Request timestamp from X-Slack-Request-Timestamp header

55

- signature: str - Request signature from X-Slack-Signature header

56

57

Returns:

58

bool - True if signature is valid, False otherwise

59

"""

60

```

61

62

### Package Information

63

64

Generates user-agent information for HTTP response headers.

65

66

```python { .api }

67

def get_package_info(self) -> str:

68

"""

69

Collect package version and system information for user-agent.

70

71

Returns:

72

str - Formatted user-agent string containing client, Python, and system versions

73

"""

74

```

75

76

### SlackServer Attributes

77

78

The SlackServer instance (accessible via `adapter.server`) provides access to internal state and configuration.

79

80

```python { .api }

81

signing_secret: str

82

"""The signing secret used for HMAC signature verification."""

83

84

emitter: SlackEventAdapter

85

"""Reference to the parent SlackEventAdapter instance."""

86

87

endpoint: str

88

"""The URL endpoint configured for receiving Slack events."""

89

90

package_info: str

91

"""User-agent string containing package version and system information."""

92

```

93

94

## Request Processing

95

96

The SlackServer automatically handles several aspects of Slack Events API requests:

97

98

### URL Verification Challenge

99

When Slack sends a challenge request to verify your endpoint:

100

```json

101

{

102

"challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"

103

}

104

```

105

106

The server automatically responds with the challenge value to complete verification.

107

108

### Event Processing

109

For actual events, the server:

110

1. Validates the request timestamp (must be within 5 minutes)

111

2. Verifies the HMAC-SHA256 signature using your signing secret

112

3. Parses the JSON event payload

113

4. Emits the event to registered listeners

114

5. Responds with HTTP 200 and custom headers

115

116

### Error Responses

117

- HTTP 403: Invalid timestamp or signature

118

- HTTP 404: GET requests (should be POST)

119

- HTTP 200: Successful event processing

120

121

## Usage Examples

122

123

### Flask Application Integration

124

125

```python

126

import os

127

from flask import Flask

128

from slackeventsapi import SlackEventAdapter

129

130

# Create your Flask app

131

app = Flask(__name__)

132

133

# Add your existing routes

134

@app.route("/health")

135

def health_check():

136

return {"status": "healthy"}

137

138

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

139

def get_data():

140

return {"data": "example"}

141

142

# Integrate Slack events

143

slack_events_adapter = SlackEventAdapter(

144

signing_secret=os.environ["SLACK_SIGNING_SECRET"],

145

endpoint="/api/slack/events", # Custom endpoint

146

server=app # Bind to existing app

147

)

148

149

@slack_events_adapter.on("message")

150

def handle_message(event_data):

151

event = event_data["event"]

152

print(f"Message: {event.get('text', '')}")

153

154

if __name__ == "__main__":

155

app.run(host="0.0.0.0", port=5000)

156

```

157

158

### Blueprint Integration

159

160

```python

161

import os

162

from flask import Blueprint

163

from slackeventsapi import SlackEventAdapter

164

165

# Create a Blueprint

166

slack_bp = Blueprint('slack', __name__, url_prefix='/slack')

167

168

# Add routes to the Blueprint

169

@slack_bp.route('/status')

170

def slack_status():

171

return {"slack": "active"}

172

173

# Bind Slack events to the Blueprint

174

slack_events_adapter = SlackEventAdapter(

175

signing_secret=os.environ["SLACK_SIGNING_SECRET"],

176

endpoint="/events", # Will be /slack/events due to Blueprint prefix

177

server=slack_bp

178

)

179

180

@slack_events_adapter.on("reaction_added")

181

def handle_reaction(event_data):

182

event = event_data["event"]

183

print(f"Reaction: {event['reaction']}")

184

185

# Register Blueprint with main app

186

from flask import Flask

187

app = Flask(__name__)

188

app.register_blueprint(slack_bp)

189

```

190

191

### Multiple Endpoints

192

193

```python

194

import os

195

from flask import Flask

196

from slackeventsapi import SlackEventAdapter

197

198

app = Flask(__name__)

199

200

# Production events

201

prod_adapter = SlackEventAdapter(

202

signing_secret=os.environ["SLACK_SIGNING_SECRET_PROD"],

203

endpoint="/slack/prod/events",

204

server=app

205

)

206

207

# Development events

208

dev_adapter = SlackEventAdapter(

209

signing_secret=os.environ["SLACK_SIGNING_SECRET_DEV"],

210

endpoint="/slack/dev/events",

211

server=app

212

)

213

214

@prod_adapter.on("message")

215

def handle_prod_message(event_data):

216

print("Production message received")

217

218

@dev_adapter.on("message")

219

def handle_dev_message(event_data):

220

print("Development message received")

221

```

222

223

### Custom Error Handling

224

225

```python

226

import os

227

from flask import Flask

228

from slackeventsapi import SlackEventAdapter

229

from slackeventsapi.server import SlackEventAdapterException

230

231

app = Flask(__name__)

232

233

slack_events_adapter = SlackEventAdapter(

234

signing_secret=os.environ["SLACK_SIGNING_SECRET"],

235

endpoint="/slack/events",

236

server=app

237

)

238

239

@slack_events_adapter.on("error")

240

def handle_slack_error(error):

241

if isinstance(error, SlackEventAdapterException):

242

error_msg = str(error)

243

244

if "Invalid request signature" in error_msg:

245

print("WARNING: Invalid signature - check signing secret")

246

# Could log to monitoring service

247

248

elif "Invalid request timestamp" in error_msg:

249

print("WARNING: Old timestamp - possible replay attack or clock skew")

250

# Could implement additional logging

251

252

else:

253

print(f"Unexpected error: {error}")

254

255

# Your app routes

256

@app.route("/")

257

def index():

258

return "Slack Events API Integration"

259

260

if __name__ == "__main__":

261

app.run(debug=True)

262

```

263

264

### Accessing Server Attributes

265

266

```python

267

import os

268

from flask import Flask

269

from slackeventsapi import SlackEventAdapter

270

271

app = Flask(__name__)

272

273

# Create adapter

274

slack_events_adapter = SlackEventAdapter(

275

signing_secret=os.environ["SLACK_SIGNING_SECRET"],

276

endpoint="/slack/events",

277

server=app

278

)

279

280

# Access server attributes for monitoring or debugging

281

print(f"Server endpoint: {slack_events_adapter.server.endpoint}")

282

print(f"Package info: {slack_events_adapter.server.package_info}")

283

print(f"Signing secret configured: {'Yes' if slack_events_adapter.server.signing_secret else 'No'}")

284

285

@app.route("/status")

286

def status():

287

return {

288

"endpoint": slack_events_adapter.server.endpoint,

289

"package_info": slack_events_adapter.server.package_info

290

}

291

292

if __name__ == "__main__":

293

app.run()

294

```

295

296

## Security Features

297

298

### Automatic Signature Verification

299

All incoming requests are automatically verified using HMAC-SHA256 with your signing secret. Invalid signatures result in HTTP 403 responses and "error" event emission.

300

301

### Timestamp Validation

302

Requests older than 5 minutes are rejected to prevent replay attacks. This protects against malicious actors replaying captured requests.

303

304

### Headers Added to Responses

305

The server adds `X-Slack-Powered-By` headers to successful responses containing package version information for debugging and monitoring.