Let's Go Further درخواست‌های Cross-Origin › نمایش خط‌مشی Same-Origin
قبلی · فهرست مطالب · بعدی
فصل ۱۷.۲.

نمایش خط‌مشی Same-Origin

برای نمایش نحوه عملکرد خط‌مشی Same-Origin و نحوه شل کردن آن برای درخواست‌های به API ما، نیاز داریم یک درخواست به API ما از یک origin متفاوت را شبیه‌سازی کنیم.

همانطور که در این کتاب از Go استفاده می‌کنیم، بیایید به سرعت یک برنامه Go دوم، بسیار ساده، برای ارسال این درخواست cross-origin بسازیم. اساساً، می‌خواهیم این برنامه دوم یک صفحه وب شامل برخی JavaScript را ارائه دهد، که به نوبه خود درخواستی به endpoint GET /v1/healthcheck ما ارسال می‌کند.

اگر دنبال می‌کنید، یک فایل cmd/examples/cors/simple/main.go جدید برای نگهداری کد این برنامه دوم ایجاد کنید:

$ mkdir -p cmd/examples/cors/simple
$ touch cmd/examples/cors/simple/main.go

و محتوای زیر را اضافه کنید:

فایل: cmd/examples/cors/simple/main.go
package main

import (
    "flag"
    "log"
    "net/http"
)

// Define a string constant containing the HTML for the webpage. This consists of a <h1>
// header tag, and some JavaScript which fetches the JSON from our GET /v1/healthcheck
// endpoint and writes it inside the <div id="output"></div> element.
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <h1>Simple CORS</h1>
    <div id="output"></div>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            fetch("http://localhost:4000/v1/healthcheck").then(
                function (response) {
                    response.text().then(function (text) {
                        document.getElementById("output").innerHTML = text;
                    });
                }, 
                function(err) {
                    document.getElementById("output").innerHTML = err;
                }
            );
        });
    </script>
</body>
</html>`

func main() {
    // Make the server address configurable at runtime via a command-line flag.
    addr := flag.String("addr", ":9000", "Server address")
    flag.Parse()

    log.Printf("starting server on %s", *addr)

    // Start an HTTP server listening on the given address, which responds to all
    // requests with the webpage HTML above.
    err := http.ListenAndServe(*addr, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(html))
    }))
    log.Fatal(err)
}

کد Go در اینجا باید برای شما آشنا باشد، اما بیایید نگاه دقیق‌تری به کد JavaScript در تگ <script> بیندازیم و توضیح دهیم چه کاری انجام می‌دهد.

<script>
    document.addEventListener('DOMContentLoaded', function() {
        fetch("http://localhost:4000/v1/healthcheck").then(
            function (response) {
                response.text().then(function (text) {
                    document.getElementById("output").innerHTML = text;
                });
            }, 
            function(err) {
                document.getElementById("output").innerHTML = err;
            }
        );
    });
</script>

در این کد:

نمایش

خب، بیایید این را امتحان کنیم. بروید و برنامه جدید را شروع کنید:

$ go run ./cmd/examples/cors/simple
2021/04/17 17:23:14 starting server on :9000

و سپس یک پنجره ترمینال دوم باز کنید و برنامه API معمولی ما را در عین حال شروع کنید:

$ go run ./cmd/api
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="database connection pool established"
time=2023-09-10T10:59:13.722+02:00 level=INFO msg="starting server" addr=:4000 env=development

در این نقطه، باید API روی origin http://localhost:4000 و صفحه وب با JavaScript روی origin http://localhost:9000 در حال اجرا باشد. از آنجا که پورت‌ها متفاوت هستند، اینها دو origin متفاوت هستند.

پس، وقتی از http://localhost:9000 در مرورگر وب خود بازدید می‌کنید، عمل fetch() به http://localhost:4000/v1/healthcheck باید توسط خط‌مشی Same-Origin ممنوع شود. به طور خاص، API ما باید درخواست را دریافت و پردازش کند، اما مرورگر وب شما باید خواندن پاسخ توسط کد JavaScript را مسدود کند.

بیایید نگاهی بیندازیم. اگر مرورگر وب خود را باز کنید و از http://localhost:9000 بازدید کنید، باید هدر Simple CORS را ببینید که با پیام خطای مشابه این دنبال می‌شود:

17.02-01.png

همچنین در اینجا مفید است که ابزارهای توسعه‌دهنده مرورگر خود را باز کنید، صفحه را تازه کنید و به لاگ کنسول خود نگاه کنید. باید پیامی ببینید که اعلام می‌کند پاسخ از endpoint GET /v1/healthcheck ما به دلیل خط‌مشی Same-Origin از خواندن مسدود شده است، مشابه این:

درخواست Cross-Origin مسدود شده: خط‌مشی Same-Origin اجازه خواندن منبع از راه دور در http://localhost:4000/v1/healthcheck را نمی‌دهد.

17.02-02.png

همچنین ممکن است بخواهید تب فعالیت شبکه در ابزارهای توسعه‌دهنده خود را باز کنید و هدرهای HTTP مرتبط با درخواست مسدود شده را بررسی کنید.

17.02-03.png

چند نکته مهم برای اشاره در اینجا وجود دارد.

اولین نکته این است که هدرها نشان می‌دهند که درخواست به API ما ارسال شده است، که درخواست را پردازش کرده و پاسخ موفق 200 OK را به مرورگر وب با تمام هدرهای پاسخ استاندارد ما بازگردانده است. برای تأکید مجدد: خود درخواست توسط خط‌مشی Same-Origin متوقف نشد — فقط مرورگر اجازه نمی‌دهد JavaScript پاسخ را ببیند.

دومین نکته این است که مرورگر وب به طور خودکار هدر Origin را روی درخواست تنظیم می‌کند تا نشان دهد درخواست از کجا منشأ می‌گیرد (توسط فلش قرمز بالا مشخص شده است). خواهید دید که هدر به این شکل است:

Origin: http://localhost:9000

ما از این هدر در فصل بعدی استفاده خواهیم کرد تا به ما کمک کند خط‌مشی Same-Origin را به طور انتخابی شل کنیم، بسته به اینکه آیا به origin که درخواست از آن می‌آید اعتماد داریم یا خیر.

در نهایت، مهم است که تأکید کنیم خط‌مشی Same-Origin فقط یک چیز مرورگر وب است.

خارج از مرورگر وب، هر کسی می‌تواند از هر جایی با استفاده از curl، wget یا هر وسیله دیگری به API ما درخواست ارسال کند و پاسخ را بخواند. این کاملاً تحت تأثیر خط‌مشی Same-Origin قرار نمی‌گیرد و تغییر نمی‌کند.