# ==============================================================================
# JUNIOR PYTHON TRACK 31 — APIs & HTTP (urllib.request & HTTP Protocol)
# ==============================================================================
import urllib.request
import json
from typing import Any, Dict, List
class MockHTTPClient:
"""Simulates HTTP Client operations for REST API endpoints."""
def __init__(self, base_url: str):
self.base_url = base_url.rstrip("/")
self.headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"User-Agent": "TeachCloud-PythonClient/1.0"
}
def format_response(self, status_code: int, body: Dict[str, Any]) -> Dict[str, Any]:
"""Parses status codes into standard API response metadata."""
status_category = f"{status_code // 100}xx"
is_success = 200 <= status_code < 300
return {
"status": status_code,
"category": status_category,
"success": is_success,
"data": body
}
def simulate_get(self, resource_id: int) -> Dict[str, Any]:
"""Simulates a GET request to read a resource."""
# Mocking server response for ID 1
if resource_id == 1:
payload = {"id": 1, "title": "Learn HTTP & APIs", "completed": True}
return self.format_response(200, payload)
else:
return self.format_response(404, {"error": "Resource Not Found"})
def simulate_post(self, payload: Dict[str, Any]) -> Dict[str, Any]:
"""Simulates a POST request to create a resource."""
if "title" not in payload:
return self.format_response(400, {"error": "Missing required field 'title'"})
created = {**payload, "id": 101, "created_at": "2026-09-20T21:15:00Z"}
return self.format_response(201, created)
if __name__ == "__main__":
client = MockHTTPClient("https://api.teachcloud.org/v1")
# 1. GET Request Simulation
get_res = client.simulate_get(1)
print(f"GET Status: {get_res['status']} | Data: {get_res['data']}")
# 2. POST Request Simulation
post_res = client.simulate_post({"title": "Build Microservices in Python", "author": "shkar"})
print(f"POST Status: {post_res['status']} | Data: {post_res['data']}")
$ python3 junior_apis_http.py
GET Status: 200 | Data: {'id': 1, 'title': 'Learn HTTP & APIs', 'completed': True}
POST Status: 201 | Data: {'title': 'Build Microservices in Python', 'author': 'shkar', 'id': 101, 'created_at': '2026-09-20T21:15:00Z'}
Execution completed successfully with returncode 0.
import unittest
class TestJuniorAPIsHTTP(unittest.TestCase):
def test_status_code_categorization(self):
status_map = {
200: ("2xx", True),
201: ("2xx", True),
400: ("4xx", False),
404: ("4xx", False),
500: ("5xx", False),
}
for code, (expected_cat, expected_success) in status_map.items():
category = f"{code // 100}xx"
is_success = 200 <= code < 300
self.assertEqual(category, expected_cat)
self.assertEqual(is_success, expected_success)
def test_http_method_idempotency(self):
idempotent_verbs = {"GET", "PUT", "DELETE", "HEAD", "OPTIONS"}
non_idempotent_verbs = {"POST", "PATCH"}
for verb in idempotent_verbs:
self.assertIn(verb, idempotent_verbs)
for verb in non_idempotent_verbs:
self.assertNotIn(verb, idempotent_verbs)
if __name__ == "__main__":
unittest.main()