-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlearning_paths.py
More file actions
134 lines (130 loc) · 8.82 KB
/
learning_paths.py
File metadata and controls
134 lines (130 loc) · 8.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
"""Guided Learning Paths — curated sequences of activities for structured HTTP learning.
Each path has an id, title, description, difficulty level, and an ordered list
of steps. Step types match existing app features:
- visit : view a status-code detail page (target = code string)
- practice: complete a scenario exercise (target = scenario id)
- debug : complete a debug exercise (target = exercise id string)
- quiz : take a quiz round (target = number of questions)
- learn : study a confusion pair lesson (target = pair slug)
"""
LEARNING_PATHS = [
{
"id": "http-foundations",
"title": "HTTP Foundations",
"description": "Start your HTTP journey with the most common success, redirect, and error codes. Build a solid base before tackling the tricky stuff.",
"difficulty": "beginner",
"steps": [
{"type": "visit", "target": "200", "label": "Visit 200 OK"},
{"type": "visit", "target": "201", "label": "Visit 201 Created"},
{"type": "visit", "target": "204", "label": "Visit 204 No Content"},
{"type": "practice", "target": 1, "label": "Practice: successful GET request"},
{"type": "practice", "target": 3, "label": "Practice: successful POST creation"},
{"type": "practice", "target": 6, "label": "Practice: successful resource deletion"},
{"type": "learn", "target": "200-vs-204", "label": "Learn: 200 OK vs 204 No Content"},
{"type": "quiz", "target": 5, "label": "Quiz: 5 questions"},
{"type": "visit", "target": "301", "label": "Visit 301 Moved Permanently"},
{"type": "visit", "target": "302", "label": "Visit 302 Found"},
{"type": "visit", "target": "404", "label": "Visit 404 Not Found"},
{"type": "practice", "target": 2, "label": "Practice: page not found"},
{"type": "practice", "target": 5, "label": "Practice: moved permanently"},
{"type": "practice", "target": 7, "label": "Practice: unauthorized access"},
],
},
{
"id": "error-whisperer",
"title": "Error Whisperer",
"description": "Master the 4xx and 5xx error codes that trip up even experienced developers. Learn to diagnose, distinguish, and debug them.",
"difficulty": "intermediate",
"steps": [
{"type": "visit", "target": "400", "label": "Visit 400 Bad Request"},
{"type": "visit", "target": "401", "label": "Visit 401 Unauthorized"},
{"type": "visit", "target": "403", "label": "Visit 403 Forbidden"},
{"type": "visit", "target": "404", "label": "Visit 404 Not Found"},
{"type": "visit", "target": "500", "label": "Visit 500 Internal Server Error"},
{"type": "learn", "target": "401-vs-403", "label": "Learn: 401 vs 403"},
{"type": "learn", "target": "400-vs-422", "label": "Learn: 400 vs 422"},
{"type": "debug", "target": "200-error-body", "label": "Debug: 200 with error body"},
{"type": "debug", "target": "403-instead-of-401", "label": "Debug: 403 instead of 401"},
{"type": "debug", "target": "500-validation-error", "label": "Debug: 500 for validation error"},
{"type": "debug", "target": "404-for-method", "label": "Debug: 404 for wrong method"},
{"type": "debug", "target": "401-no-www-auth", "label": "Debug: 401 without WWW-Authenticate"},
{"type": "practice", "target": 9, "label": "Practice: rate-limited API"},
{"type": "practice", "target": 10, "label": "Practice: wrong HTTP method"},
{"type": "practice", "target": 11, "label": "Practice: conflict on update"},
{"type": "practice", "target": 12, "label": "Practice: payload too large"},
{"type": "practice", "target": 13, "label": "Practice: unsupported media type"},
],
},
{
"id": "redirect-master",
"title": "Redirect Master",
"description": "Conquer the full family of 3xx redirect codes. Understand when to use permanent vs temporary, and when method preservation matters.",
"difficulty": "advanced",
"steps": [
{"type": "visit", "target": "300", "label": "Visit 300 Multiple Choices"},
{"type": "visit", "target": "301", "label": "Visit 301 Moved Permanently"},
{"type": "visit", "target": "302", "label": "Visit 302 Found"},
{"type": "visit", "target": "303", "label": "Visit 303 See Other"},
{"type": "visit", "target": "304", "label": "Visit 304 Not Modified"},
{"type": "visit", "target": "307", "label": "Visit 307 Temporary Redirect"},
{"type": "visit", "target": "308", "label": "Visit 308 Permanent Redirect"},
{"type": "learn", "target": "301-vs-302", "label": "Learn: 301 vs 302"},
{"type": "learn", "target": "307-vs-308", "label": "Learn: 307 vs 308"},
{"type": "learn", "target": "302-vs-307", "label": "Learn: 302 vs 307"},
{"type": "practice", "target": 18, "label": "Practice: permanent API move"},
{"type": "practice", "target": 19, "label": "Practice: method-preserving redirect"},
{"type": "practice", "target": 20, "label": "Practice: POST/redirect/GET pattern"},
{"type": "practice", "target": 21, "label": "Practice: conditional caching"},
{"type": "practice", "target": 22, "label": "Practice: partial content response"},
{"type": "debug", "target": "301-no-location", "label": "Debug: 301 missing Location"},
{"type": "debug", "target": "302-post-form", "label": "Debug: 302 drops POST body"},
{"type": "debug", "target": "post-301-redirect", "label": "Debug: POST with 301 redirect"},
],
},
{
"id": "api-designer",
"title": "API Designer",
"description": "Learn to pick the right status codes for REST APIs. Cover CRUD operations, error handling, rate limiting, and content negotiation.",
"difficulty": "intermediate",
"steps": [
{"type": "visit", "target": "200", "label": "Visit 200 OK"},
{"type": "visit", "target": "201", "label": "Visit 201 Created"},
{"type": "visit", "target": "204", "label": "Visit 204 No Content"},
{"type": "visit", "target": "422", "label": "Visit 422 Unprocessable Entity"},
{"type": "learn", "target": "200-vs-204", "label": "Learn: 200 OK vs 204 No Content"},
{"type": "learn", "target": "400-vs-422", "label": "Learn: 400 vs 422"},
{"type": "practice", "target": 1, "label": "Practice: successful GET"},
{"type": "practice", "target": 3, "label": "Practice: successful POST creation"},
{"type": "visit", "target": "429", "label": "Visit 429 Too Many Requests"},
{"type": "learn", "target": "429-vs-503", "label": "Learn: 429 vs 503"},
{"type": "visit", "target": "401", "label": "Visit 401 Unauthorized"},
{"type": "visit", "target": "403", "label": "Visit 403 Forbidden"},
{"type": "learn", "target": "401-vs-403", "label": "Learn: 401 vs 403"},
{"type": "practice", "target": 7, "label": "Practice: unauthorized access"},
{"type": "practice", "target": 9, "label": "Practice: rate-limited API"},
{"type": "debug", "target": "200-error-body", "label": "Debug: 200 with error body"},
{"type": "quiz", "target": 10, "label": "Quiz: 10 questions"},
],
},
{
"id": "security-sentinel",
"title": "Security Sentinel",
"description": "Master HTTP security: authentication, authorization, CORS, and security headers. Learn to build APIs that are secure by default.",
"difficulty": "advanced",
"steps": [
{"type": "visit", "target": "401", "label": "Visit 401 Unauthorized"},
{"type": "visit", "target": "403", "label": "Visit 403 Forbidden"},
{"type": "learn", "target": "401-vs-403", "label": "Learn: 401 vs 403"},
{"type": "debug", "target": "401-no-www-auth", "label": "Debug: 401 missing WWW-Authenticate"},
{"type": "debug", "target": "403-instead-of-401", "label": "Debug: 403 used instead of 401"},
{"type": "debug", "target": "cors-missing-origin", "label": "Debug: CORS missing Allow-Origin"},
{"type": "visit", "target": "451", "label": "Visit 451 Unavailable For Legal Reasons"},
{"type": "visit", "target": "511", "label": "Visit 511 Network Authentication Required"},
{"type": "practice", "target": 59, "label": "Practice: expired JWT token"},
{"type": "practice", "target": 7, "label": "Practice: unauthorized access"},
{"type": "quiz", "target": 10, "label": "Quiz: 10 questions"},
],
},
]
# Quick lookup by path id
LEARNING_PATHS_BY_ID = {p["id"]: p for p in LEARNING_PATHS}