وبلاگ نت‌آرامآموزش، تجربه و راهکارهای زیرساخت

Flask در زیرمسیر هاست لینک اشتباه می‌سازد؛ رفع 404 پشت پراکسی

آموزش تشخیص و تنظیم پیشوند مسیر Flask پشت reverse proxy و ساخت درست لینک‌ها.

انتشار:
توسط تیم فنی نت‌آرام
۵ دقیقه زمان مطالعه
۰ دیدگاه
محتوای تخصصی، ساده و کاربردی
هماهنگ با هویت حرفه‌ای نت‌آرام
بازگشت به لیست مقالات
تصویر شاخص مقاله Flask در زیرمسیر هاست لینک اشتباه می‌سازد؛ رفع 404 پشت پراکسی در وبلاگ نت‌آرام
محتوای آموزشی وبلاگ نت‌آرام
برنامه Flask را زیر نشانی example.com/app/ قرار داده‌اید. صفحه اصلی شاید باز شود، اما لینک ورود یا فایل CSS به example.com/login می‌رود و ۴۰۴ می‌دهد؛ پیشوند /app از نشانی جا افتاده است. گاهی برعکس، پیشوند دو بار اضافه می‌شود.
علت می‌تواند اختلاف مسیر عمومی، مسیری که پراکسی به Flask می‌فرستد و روشی باشد که برنامه برای ساخت لینک استفاده می‌کند. ابتدا این سه مسیر را از هم جدا می‌کنیم؛ سپس در صورت نیاز اطلاعات پیشوند را فقط از پراکسی قابل اعتماد می‌پذیریم.

۱. یک مسیر واقعی را دنبال کنید

در مرورگر F12 و زبانه Network را باز کنید. صفحه /app/ را باز و روی لینک خراب کلیک کنید. نشانی درخواستی، وضعیت و هدر Location در تغییر مسیر را ببینید. آیا مرورگر به /login، /app/login یا /app/app/login رفته است؟ اطلاعات نشست و کوکی را در گزارش عمومی منتشر نکنید.
سپس در تنظیم پراکسی، آدرس upstream و رفتار حذف یا نگه‌داشتن پیشوند را بخوانید. برای نمونه، در برخی پیکربندی‌های Nginx وجود یا نبود / در انتهای proxy_pass بر جایگزینی مسیر اثر دارد. بدون دیدن location و نشانی مقصد نمی‌توان نسخه واحدی برای همه سرورها تجویز کرد.

۲. نمونه کوچک Flask را محلی آزمایش کنید

در یک پروژه آزمایشی، برنامه‌ای با دو مسیر ساده داشته باشید:
کد / دستورfrom flask import Flask, redirect, url_for app = Flask(__name__) @app.route("/") def home(): return redirect(url_for("login")) @app.route("/login") def login(): return "Test login page"
این نمونه هیچ ورود واقعی یا اطلاعات کاربر ندارد. با ابزار تست Flask، مسیر تولیدشده در درخواست عادی را می‌توان دید:
کد / دستورwith app.test_client() as client: response = client.get("/") print(response.status_code, response.headers.get("Location"))
قطعه دوم را بعد از تعریف برنامه در یک فایل آزمایشی اجرا کنید. در ریشه برنامه، نتیجه معمولاً تغییر مسیر به /login است. حالا باید مشخص شود پراکسی چگونه پیشوند عمومی را به برنامه اطلاع می‌دهد.

۳. پیشوند را فقط از پراکسی مورد اعتماد بگیرید

اگر دقیقاً یک پراکسی مورد اعتماد در جلوی برنامه وجود دارد، هدر X-Forwarded-Prefix را خودش بازنویسی می‌کند و دسترسی مستقیم کاربران به برنامه بسته است، در نسخه سازگار Werkzeug می‌توان از ProxyFix استفاده کرد:
کد / دستورfrom werkzeug.middleware.proxy_fix import ProxyFix app.wsgi_app = ProxyFix( app.wsgi_app, x_for=0, x_proto=0, x_host=0, x_port=0, x_prefix=1, )
این قطعه باید بعد از ساخت app و پیش از شروع سرویس قرار گیرد. عدد 1 به معنی اعتماد به یک مقدار از پراکسی است؛ با تعداد و ترتیب واقعی پراکسی‌های شما ممکن است متفاوت باشد. تنظیم نادرست باعث می‌شود کاربر هدر جعلی بفرستد و نشانی‌های برنامه را تحت تأثیر قرار دهد. گزینه‌های دیگر را نیز بدون نیاز و شناخت مسیر واقعی فعال نکنید.
پراکسی باید هدر پیشوند را با مقدار درست خودش جایگزین کند، نه اینکه مقدار دلخواه کاربر را بدون بررسی عبور دهد. اگر کنترل تنظیم پراکسی در هاست اشتراکی ندارید، از پشتیبانی درباره روش رسمی زیرمسیر و هدرهای موجود بپرسید.

۴. لینک‌ها و فایل‌های استاتیک را اصلاح کنید

در قالب‌ها به جای نوشتن ثابت /login، از url_for برای ساخت مسیرهای مربوط به برنامه استفاده کنید. اگر فایل CSS با مسیر ثابت /static/style.css نوشته شده، ممکن است پیشوند را نگیرد؛ نشانی آن را نیز از سازوکار Flask یا تنظیم build پروژه بسازید.
APPLICATION_ROOT در بعضی موارد مانند ساخت URL خارج از زمینه درخواست کاربرد دارد، اما به تنهایی تنظیم پراکسی یا مسیردهی همه درخواست‌ها را جایگزین نمی‌کند. اگر برنامه خود routeها را با پیشوند تعریف کرده و پراکسی نیز همان را دوباره اضافه می‌کند، مسیر دو بار تکرار می‌شود؛ مسئولیت هر لایه را روشن کنید.

۵. نتیجه و امنیت را آزمایش کنید

صفحه اصلی، تغییر مسیر ورود، یک لینک داخلی و یک فایل استاتیک را از نشانی عمومی /app/ امتحان کنید. در محیط آزمایشی، دسترسی مستقیم و ارسال هدر جعلی را نیز با مدیر بررسی کنید؛ نباید کاربر ناشناس بتواند پیشوند مورد اعتماد را تعیین کند. پس از هر تغییر پراکسی، تنظیم قبلی و روش بازگشت را نگه دارید.
اگر صفحه اصلی درست شد ولی پس از ورود دوباره به صفحه ورود برمی‌گردید، در Network پاسخ ورود و مسیر کوکی را جداگانه ببینید. برای برنامه‌ای که فقط زیر /app/ کار می‌کند، مسیر کوکی باید درخواست‌های همان زیرمسیر را پوشش دهد؛ تنظیم کوکی و نام دامنه آن به برنامه و شیوه استقرار بستگی دارد. ابتدا در مرورگر ناشناس با کوکی تازه امتحان کنید تا تنظیم قدیمی نتیجه را گمراه نکند. مقدار کوکی نشست را برای دیگران ارسال نکنید.
اگر برنامه با نشانی مستقیم داخلی درست است اما از آدرس عمومی ۴۰۴ می‌دهد، نشانی رسیده به Flask را در محیط آزمایشی ثبت کنید. مثلاً در یک route آزمایشی، مقادیر request.path و request.script_root را ببینید: اولی مسیر داخل برنامه و دومی پیشوند استقرار را نشان می‌دهد. این خروجی تشخیصی را پیش از انتشار حذف کنید و هیچ اطلاعات درخواست خصوصی را در صفحه عمومی نشان ندهید.
اگر برنامه اصلاً در Passenger شروع نمی‌شود، راهنمای فایل WSGI مسیر جداگانه‌ای دارد. مشخصات هاست پایتون نت‌آرام و توضیح اعتماد به هدرهای پراکسی در Werkzeug را ببینید.
اشتراک‌گذاری:
لینکدینتلگرامایکس

دیدگاه‌ها (۰)

دیدگاه‌های تاییدشده و پاسخ‌های تیم نت‌آرام