کتابخانه‌ی استاندارد · شبکه

میان افزار net/http/middleware

سرآیندهای رایج امنیت، کش و CORS و ثبت درخواست‌ها، در یک صدا زدن.

واردسازی شبکه.اچ تی تی پی.میان افزار

پنج تابع کمکی کوچک برای گرداننده‌های اچ تی تی پی: اجازه به همه برای CORS، امن برای سرآیندهای امنیتی پایه، بدون کش و کش برای کش، و ثبت رخداد برای یک سطر به ازای هر درخواست. هر کدام مثل خود گرداننده شناسه‌ی زمینه را می‌گیرد و فقط سرآیند پاسخ می‌گذارد (یا چاپ می‌کند)، پس آن‌ها را در سطرهای اول گرداننده صدا می‌زنید.

سلام زنجیره‌ی میان‌افزار ندارد و نمی‌شود گرداننده را از بیرون پوشاند. میان‌افزار یک تابع معمولی است که با شناسه‌ی زمینه صدا زده می‌شود و سرآیندهایی که می‌گذارد همراه هر چیزی که گرداننده پس از آن می‌نویسد فرستاده می‌شوند. این‌طور ترتیب کار در خود گرداننده پیداست. برای ورود کاربر نشست و برای بررسی ورودی اعتبارسنجی را ببینید.

پیش از تکیه بر این تابع‌ها بدانید:

  • اجازه به همه روش PATCH را فهرست نمی‌کند. برای همه‌ی مبدأها روش‌های GET، POST، PUT، DELETE و OPTIONS را با سرآیندهای Content-Type و Authorization مجاز می‌کند. مرورگر PATCH از مبدأ دیگر را رد می‌کند و * با کوکی کار نمی‌کند؛ برای این‌ها قاعده‌ی خودتان را بنویسید (بخش آخر).
  • امن حداقل است. nosniff، X-Frame-Options: DENY و X-XSS-Protection را می‌گذارد که مرورگرهای امروزی نادیده‌اش می‌گیرند. Content-Security-Policy و Strict-Transport-Security نمی‌گذارد.
  • آخرین فراخوانی برنده است. سرآیندی که دو بار با یک نام گذاشته شود مقدار آخر را نگه می‌دارد، پس بدون کش و پس از آن کش فقط max-age را باقی می‌گذارد.
  • ثبت رخداد پیش از اجرای گرداننده با سرچاپ چاپ می‌کند، پس وضعیت را نشان نمی‌دهد؛ اچ تی تی پی.فعال سازی گزارش دسترسی روی سرور وضعیت را هم ثبت می‌کند.

CORS برای API که از مرورگر صدا زده می‌شود

صفحه‌ای از یک مبدأ دیگر فقط وقتی می‌تواند API شما را صدا بزند که پاسخ اجازه دهد. برای هر چیزی جز یک GET ساده، مرورگر اول یک درخواست OPTIONS می‌فرستد که به آن پیش‌پرواز می‌گویند و سرآیندهای Access-Control-Allow-* پاسخ را بررسی می‌کند. یک مسیر OPTIONS ثبت کنید که اجازه به همه را صدا بزند و با ۲۰۴ و بدون بدنه پاسخ دهد، و در گرداننده‌ی اصلی هم اجازه به همه را صدا بزنید.

net-http-middleware-cors.salam
واردسازی شبکه.اچ تی تی پی
واردسازی شبکه.اچ تی تی پی.میان افزار
واردسازی شبکه.مسیریاب

تابع پیش پرواز(ز: صحیح۶۴):
    میان افزار.اجازه به همه(ز)
    اچ تی تی پی.تنظیم وضعیت(ز، ۲۰۴)
    اچ تی تی پی.متن(ز، "")
پایان

تابع یادداشت‌ها(ز: صحیح۶۴):
    میان افزار.اجازه به همه(ز)
    میان افزار.بدون کش(ز)
    اچ تی تی پی.جیسون(ز، `[{"id":1,"text":"نان بخر"}]`)
پایان

تابع ریشه:
    ناپایا م := مسیریاب.مسیریاب جدید()
    مسیریاب.گزینه ها(م، "/api/notes"، پیش پرواز)
    مسیریاب.دریافت(م، "/api/notes"، یادداشت‌ها)
    ناپایا س := اچ تی تی پی.سرور جدید(۱۹۷۸۵)
    اچ تی تی پی.استفاده(س، م)
    _ := اچ تی تی پی.اجرا در پس زمینه(س)
    نشانی := "http://127.0.0.1:19785/api/notes"
    ناپایا سر := اچ تی تی پی.سرصفحه جدید()
    سر.درج("Origin"، "https://app.example.com")
    سر.درج("Access-Control-Request-Method"، "GET")
    پ := اچ تی تی پی.گزینه ها با(نشانی، سر)
    سرچاپ "پیش پرواز:"، اچ تی تی پی.وضعیت(پ)
    هر نام در ["access-control-allow-origin"، "access-control-allow-methods"، "access-control-allow-headers"]:
        سرچاپ "  " + نام + ": " + اچ تی تی پی.دریافت سرصفحه(پ، نام)
    پایان
    د := اچ تی تی پی.دریافت با(نشانی، سر)
    سرچاپ "دریافت:"، اچ تی تی پی.وضعیت(د)، اچ تی تی پی.بدنه(د)
    سرچاپ "  cache-control: " + اچ تی تی پی.دریافت سرصفحه(د، "cache-control")
    سرچاپ "  pragma: " + اچ تی تی پی.دریافت سرصفحه(د، "pragma")
پایان
خروجیپیش پرواز: 204 access-control-allow-origin: * access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS access-control-allow-headers: Content-Type, Authorization دریافت: 200 [{"id":1,"text":"نان بخر"}] cache-control: no-store, no-cache, must-revalidate pragma: no-cache

اجازه به همه به همه‌ی مبدأها، روش‌های GET، POST، PUT، DELETE و OPTIONS (نه PATCH) و سرآیندهای Content-Type و Authorization اجازه می‌دهد. این برای یک API عمومی و فقط‌خواندنی مناسب است. APIای که کوکی یا سرآیندهای دیگر به کار می‌برد قاعده‌ی خودش را لازم دارد، همان‌طور که بخش آخر نشان می‌دهد.

یک تابع کمکی برای هر نوع پاسخ

به جای تکرار همان صدا زدن‌ها در ابتدای هر گرداننده، آن‌ها را برای هر نوع پاسخ در یک تابع جمع کنید: صفحه‌های خصوصی که نباید کش شوند و نباید در قاب دیده شوند، و پرونده‌های عمومی که مرورگر می‌تواند نگه دارد. امن سرآیندهای nosniff، X-Frame-Options: DENY و سرآیند XSS را می‌گذارد؛ بدون کش کش کردن را ممنوع می‌کند؛ کش آن را برای چند ثانیه‌ی داده‌شده مجاز می‌کند.

net-http-middleware-chain.salam
واردسازی شبکه.اچ تی تی پی
واردسازی شبکه.اچ تی تی پی.میان افزار
واردسازی شبکه.مسیریاب

تابع سرآیند صفحه(ز: صحیح۶۴):
    میان افزار.امن(ز)
    میان افزار.بدون کش(ز)
پایان

تابع سرآیند فایل(ز: صحیح۶۴، ثانیه: صحیح):
    میان افزار.کش(ز، ثانیه)
پایان

تابع حساب(ز: صحیح۶۴):
    سرآیند صفحه(ز)
    اچ تی تی پی.اچ تی ام ال(ز، "<h1>حساب شما</h1>")
پایان

تابع نشان(ز: صحیح۶۴):
    سرآیند فایل(ز، ۸۶۴۰۰)
    اچ تی تی پی.متن(ز، "logo bytes")
پایان

تابع اخبار(ز: صحیح۶۴):
    سرآیند فایل(ز، ۶۰)
    اچ تی تی پی.جیسون(ز، `["نسخه 0.5.5"]`)
پایان

تابع ریشه:
    ناپایا م := مسیریاب.مسیریاب جدید()
    مسیریاب.دریافت(م، "/account"، حساب)
    مسیریاب.دریافت(م، "/logo.svg"، نشان)
    مسیریاب.دریافت(م، "/news.json"، اخبار)
    ناپایا س := اچ تی تی پی.سرور جدید(۱۹۷۸۶)
    اچ تی تی پی.استفاده(س، م)
    _ := اچ تی تی پی.اجرا در پس زمینه(س)
    پایه := "http://127.0.0.1:19786"
    هر مسیر در ["/account"، "/logo.svg"، "/news.json"]:
        پ := اچ تی تی پی.دریافت(پایه + مسیر)
        سرچاپ مسیر + " cache-control=" + اچ تی تی پی.دریافت سرصفحه(پ، "cache-control") + " frame=" + اچ تی تی پی.دریافت سرصفحه(پ، "x-frame-options")
    پایان
پایان
خروجی/account cache-control=no-store, no-cache, must-revalidate frame=DENY /logo.svg cache-control=max-age=86400 frame= /news.json cache-control=max-age=60 frame=

ثبت رخداد برای هر درخواست یک خط با روش و مسیر چاپ می‌کند که هنگام توسعه کمک می‌کند. در محیط واقعی، اچ تی تی پی.فعال سازی گزارش دسترسی روی سرور هر درخواست را با وضعیتش ثبت می‌کند، بی آنکه در هر گرداننده چیزی صدا بزنید.

سرآیندهای سخت‌گیرانه‌تر برای صفحه‌های خصوصی

برای صفحه‌ی فاکتور یا حساب کاربری، سرآیندهایی را که امن نمی‌گذارد خودتان اضافه کنید: یک Content-Security-Policy که فقط اجازه‌ی بارگیری از مبدأ خود صفحه را می‌دهد، Strict-Transport-Security تا مرورگر روی HTTPS بماند (فقط وقتی سایت روی HTTPS است بفرستید) و یک Referrer-Policy. مسیر دوم قاعده‌ی «آخرین فراخوانی برنده است» را نشان می‌دهد: بدون کش و سپس کش را صدا می‌زند و پاسخ فقط یک Cache-Control با مقدار دوم دارد.

net-http-middleware-strict.salam
واردسازی شبکه.اچ تی تی پی
واردسازی شبکه.اچ تی تی پی.میان افزار
واردسازی شبکه.مسیریاب

تابع سخت‌گیرانه(ز: صحیح۶۴):
    میان افزار.امن(ز)
    اچ تی تی پی.تنظیم سرصفحه(ز، "Content-Security-Policy"، "default-src 'self'")
    اچ تی تی پی.تنظیم سرصفحه(ز، "Strict-Transport-Security"، "max-age=31536000")
    اچ تی تی پی.تنظیم سرصفحه(ز، "Referrer-Policy"، "same-origin")
پایان

تابع فاکتور(ز: صحیح۶۴):
    سخت‌گیرانه(ز)
    میان افزار.بدون کش(ز)
    اچ تی تی پی.اچ تی ام ال(ز، "<h1>فاکتور ۱۰۴۲</h1>")
پایان

تابع گزارش(ز: صحیح۶۴):
    میان افزار.بدون کش(ز)
    میان افزار.کش(ز، ۳۰۰)
    اچ تی تی پی.متن(ز، "گزارش ماهانه")
پایان

تابع ریشه:
    ناپایا م := مسیریاب.مسیریاب جدید()
    مسیریاب.دریافت(م، "/invoice"، فاکتور)
    مسیریاب.دریافت(م، "/report"، گزارش)
    ناپایا س := اچ تی تی پی.سرور جدید(۱۸۶۴۲)
    اچ تی تی پی.تنظیم میزبان(س، "127.0.0.1")
    اچ تی تی پی.استفاده(س، م)
    اگر وارونه اچ تی تی پی.اجرا در پس زمینه(س):
        سرچاپ "درگاه ۱۸۶۴۲ گرفته است"
        برگشت ۱
    پایان
    الف := اچ تی تی پی.دریافت("http://127.0.0.1:18642/invoice")
    هر نام در ["x-frame-options"، "content-security-policy"، "strict-transport-security"، "referrer-policy"]:
        سرچاپ نام + ": " + اچ تی تی پی.دریافت سرصفحه(الف، نام)
    پایان
    ب := اچ تی تی پی.دریافت("http://127.0.0.1:18642/report")
    سرچاپ "سطرهای cache-control در /report:"، اچ تی تی پی.مقادیر سرصفحه(ب، "cache-control")
    برگشت ۰
پایان
خروجیx-frame-options: DENY content-security-policy: default-src 'self' strict-transport-security: max-age=31536000 referrer-policy: same-origin سطرهای cache-control در /report: ["max-age=300"]

سیاست default-src 'self' اسکریپت درون‌خطی <script> و ویژگی style را هم می‌بندد، پس پیش از روشن کردنش صفحه‌هایتان را با آن بیازمایید.

نوشتن میان‌افزار خودتان

وقتی سرآیندهای آماده مناسب نیستند، تابعی با همان شکل بنویسید. تابعی که فقط سرآیند اضافه می‌کند چیزی برنمی‌گرداند. تابعی که ممکن است درخواست را متوقف کند منطقی برمی‌گرداند: خودش پاسخ خطا را می‌نویسد و نادرست برمی‌گرداند، و گرداننده همان‌جا برمی‌گردد. این نمونه فقط به یک مبدأ مورد اعتماد اجازه می‌دهد و فقط بدنه‌ی جیسون می‌پذیرد.

net-http-middleware-own.salam
واردسازی شبکه.اچ تی تی پی
واردسازی شبکه.اچ تی تی پی.میان افزار
واردسازی شبکه.مسیریاب

تابع اجازه به مبدا(ز: صحیح۶۴، مبدا: رشته):
    اگر اچ تی تی پی.سرصفحه(ز، "Origin") برابر مبدا:
        اچ تی تی پی.تنظیم سرصفحه(ز، "Access-Control-Allow-Origin"، مبدا)
        اچ تی تی پی.تنظیم سرصفحه(ز، "Vary"، "Origin")
    پایان
پایان

تابع جیسون لازم(ز: صحیح۶۴): منطقی:
    اگر اچ تی تی پی.سرصفحه(ز، "Content-Type").شروع با("application/json"):
        برگشت درست
    پایان
    اچ تی تی پی.تنظیم وضعیت(ز، ۴۱۵)
    اچ تی تی پی.جیسون(ز، `{"error":"جیسون بفرستید"}`)
    برگشت نادرست
پایان

تابع ثبت سفارش(ز: صحیح۶۴):
    میان افزار.امن(ز)
    اجازه به مبدا(ز، "https://shop.example.com")
    اگر وارونه جیسون لازم(ز): برگشت پایان
    اچ تی تی پی.تنظیم وضعیت(ز، ۲۰۱)
    اچ تی تی پی.جیسون(ز، اچ تی تی پی.بدنه(ز))
پایان

تابع ریشه:
    ناپایا م := مسیریاب.مسیریاب جدید()
    مسیریاب.ارسال(م، "/orders"، ثبت سفارش)
    ناپایا س := اچ تی تی پی.سرور جدید(۱۹۷۸۷)
    اچ تی تی پی.استفاده(س، م)
    _ := اچ تی تی پی.اجرا در پس زمینه(س)
    نشانی := "http://127.0.0.1:19787/orders"
    ناپایا سرآیند مجاز := اچ تی تی پی.سرصفحه جدید()
    سرآیند مجاز.درج("Origin"، "https://shop.example.com")
    سرآیند مجاز.درج("Content-Type"، "application/json")
    پ := اچ تی تی پی.ارسال با(نشانی، `{"item":"چای"}`، سرآیند مجاز)
    سرچاپ اچ تی تی پی.وضعیت(پ)، اچ تی تی پی.بدنه(پ)، "[" + اچ تی تی پی.دریافت سرصفحه(پ، "access-control-allow-origin") + "]"
    ناپایا بیگانه := اچ تی تی پی.سرصفحه جدید()
    بیگانه.درج("Origin"، "https://evil.example")
    بیگانه.درج("Content-Type"، "text/plain")
    ب := اچ تی تی پی.ارسال با(نشانی، "item=tea"، بیگانه)
    سرچاپ اچ تی تی پی.وضعیت(ب)، اچ تی تی پی.بدنه(ب)، "[" + اچ تی تی پی.دریافت سرصفحه(ب، "access-control-allow-origin") + "]"
پایان
خروجی201 {"item":"چای"} [https://shop.example.com] 415 {"error":"جیسون بفرستید"} []

هر جا پاسخ به سرآیند Origin بستگی دارد، Vary: Origin را هم بفرستید تا کش مشترک پاسخ یک مبدأ را به مبدأ دیگری ندهد.

کدام تابع برای کدام کار

کارتابع
صفحه‌های هر مبدأیی بتوانند API را صدا بزننداجازه به همه
محافظت پایه برای صفحه‌های HTMLامن
صفحه‌های دارای داده‌ی خصوصیبدون کش
تصویر، سبک و اسکریپتی که کم تغییر می‌کندکش با شمار ثانیه
دیدن درخواست‌ها هنگام توسعهثبت رخداد

تابع‌ها

ثبت رخداد Log

تابع ثبت رخداد(ctx: صحیح۶۴)
[HTTP]، روش و مسیر درخواست را در خروجی استاندارد چاپ می‌کند؛ وضعیت را نه، چون پیش از پاسخ گرداننده اجرا می‌شود.
net-http-middleware-Headers.salam
واردسازی شبکه.اچ تی تی پی
واردسازی شبکه.اچ تی تی پی.میان افزار
واردسازی شبکه.مسیریاب

تابع خانه(ز: صحیح۶۴):
    میان افزار.ثبت رخداد(ز)
    میان افزار.اجازه به همه(ز)
    میان افزار.امن(ز)
    میان افزار.بدون کش(ز)
    اچ تی تی پی.متن(ز، "سلام")
پایان

تابع عکس(ز: صحیح۶۴):
    میان افزار.کش(ز، ۳۶۰۰)
    اچ تی تی پی.متن(ز، "png")
پایان

تابع ریشه:
    ناپایا م := مسیریاب.مسیریاب جدید()
    مسیریاب.دریافت(م، "/"، خانه)
    مسیریاب.دریافت(م، "/logo.png"، عکس)
    ناپایا س := اچ تی تی پی.سرور جدید(۱۹۶۰۴)
    اچ تی تی پی.استفاده(س، م)
    _ := اچ تی تی پی.اجرا در پس زمینه(س)
    پ := اچ تی تی پی.دریافت("http://127.0.0.1:19604/")
    هر نام در ["access-control-allow-origin"، "x-content-type-options"، "x-frame-options"، "cache-control"]:
        سرچاپ نام + ": " + اچ تی تی پی.دریافت سرصفحه(پ، نام)
    پایان
    سرچاپ اچ تی تی پی.دریافت سرصفحه(اچ تی تی پی.دریافت("http://127.0.0.1:19604/logo.png")، "cache-control")
پایان
خروجی[HTTP] GET / access-control-allow-origin: * x-content-type-options: nosniff x-frame-options: DENY cache-control: no-store, no-cache, must-revalidate max-age=3600

اجازه به همه AllowAll

تابع اجازه به همه(ctx: صحیح۶۴)
CORS را برای همه‌ی مبدأها باز می‌کند: Access-Control-Allow-Origin: *، روش‌های GET، POST، PUT، DELETE و OPTIONS و سرآیندهای Content-Type و Authorization. PATCH در فهرست نیست.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-http-middleware-Headers.salam

امن Secure

تابع امن(ctx: صحیح۶۴)
سرآیندهای X-Content-Type-Options: nosniff، X-Frame-Options: DENY و X-XSS-Protection: 1; mode=block را می‌گذارد. CSP و HSTS ندارد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-http-middleware-Headers.salam

بدون کش NoCache

تابع بدون کش(ctx: صحیح۶۴)
به مرورگر و پراکسی‌ها می‌گوید پاسخ را نگه ندارند: Cache-Control: no-store, no-cache, must-revalidate و Pragma: no-cache.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-http-middleware-Headers.salam

کش Cache

تابع کش(ctx: صحیح۶۴، seconds: صحیح)
Cache-Control: max-age= را با این تعداد ثانیه می‌گذارد و جای Cache-Control قبلی را می‌گیرد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: net-http-middleware-Headers.salam