# ===== CodeLab: net-cors =====
# 以下代码片段按文章出现顺序拼接, 共 6 段

# ----- 片段 1 (bash) -----
# 假设 127.0.0.1:8000 上跑着一个 API
curl -i http://127.0.0.1:8000/api

# ----- 片段 2 (javascript) -----
// 在 localhost:3000 的页面上请求 8000 端口的接口
fetch("http://127.0.0.1:8000/api")
  .then(r => r.json())
  .then(data => console.log(data))
  .catch(err => console.error("被拦截:", err.message));

# ----- 片段 3 (python) -----
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
import http.client

class Api(BaseHTTPRequestHandler):
    def do_GET(self):
        # 注意:这里故意不加任何 CORS 头
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(b'{"message": "hello"}')

    def log_message(self, *args):
        pass

server = HTTPServer(("127.0.0.1", 0), Api)
port = server.server_address[1]
threading.Thread(target=server.serve_forever, daemon=True).start()

conn = http.client.HTTPConnection("127.0.0.1", port, timeout=3)
conn.request("GET", "/api", headers={"Origin": "http://localhost:3000"})
r = conn.getresponse()
print("状态码:", r.status)
print("Access-Control-Allow-Origin:", r.getheader("Access-Control-Allow-Origin"))
conn.close()

server.shutdown()

# ----- 片段 4 (python) -----
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
import http.client

class Api(BaseHTTPRequestHandler):
    def _cors(self):
        # 回显 Origin,而不是写死 *,方便后续支持带凭据的请求
        origin = self.headers.get("Origin", "*")
        self.send_header("Access-Control-Allow-Origin", origin)

    def do_OPTIONS(self):
        # 预检请求:回答"允许哪些方法、哪些请求头"
        self.send_response(204)
        self._cors()
        self.send_header("Access-Control-Allow-Methods",
                         "GET, POST, PUT, DELETE, OPTIONS")
        self.send_header("Access-Control-Allow-Headers",
                         "Content-Type, Authorization")
        self.end_headers()

    def do_GET(self):
        self.send_response(200)
        self._cors()
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(b'{"message": "hello"}')

    def log_message(self, *args):
        pass

server = HTTPServer(("127.0.0.1", 0), Api)
port = server.server_address[1]
threading.Thread(target=server.serve_forever, daemon=True).start()

def probe(method, path, headers):
    conn = http.client.HTTPConnection("127.0.0.1", port, timeout=3)
    conn.request(method, path, headers=headers)
    r = conn.getresponse()
    print(method, path, "->", r.status,
          "| ACAO:", r.getheader("Access-Control-Allow-Origin"),
          "| Allow-Headers:", r.getheader("Access-Control-Allow-Headers"))
    conn.close()

probe("GET", "/api", {"Origin": "http://localhost:3000"})
probe("OPTIONS", "/api", {"Origin": "http://localhost:3000",
                          "Access-Control-Request-Method": "GET"})
server.shutdown()

# ----- 片段 5 (bash) -----
curl -i -H "Origin: http://localhost:3000" http://127.0.0.1:8000/api
# 响应头里应该能看到:
# Access-Control-Allow-Origin: http://localhost:3000

# ----- 片段 6 (bash) -----
# 浏览器访问 /api 时,代理转发到后端服务
location /api/ {
    proxy_pass http://127.0.0.1:8000;
    add_header Access-Control-Allow-Origin *;
}
