CHA-CGI(5) File Formats Manual CHA-CGI(5)

cha-cgi - رابط CGI و پروتکل اسکریپت‌نویسی مرورگر وب متنی chawan

برنامه Chawan از فراخوانی اسکریپت‌های CGI قرارگرفته در دایرکتوری مشخص‌شده در گزینه پیکربندی external.cgi-dir پشتیبانی می‌کند. به‌طور پیش‌فرض، این گزینه روی $CHA_DIR/cgi-bin (یعنی ~/.chawan/cgi-bin یا ~/.config/chawan/cgi-bin، بسته به مکان config.toml) و /usr/local/libexec/chawan/cgi-bin تنظیم شده است.

یک اسکریپت CGI در یکی از این دایرکتوری‌ها می‌تواند با باز کردن نشانی cgi-bin:script-name اجرا شود. متغیرهای $PATH_INFO و $QUERY_STRING طبق معمول تنظیم می‌شوند، یعنی cgi-bin:script-name/abcd?defgh=ijkl مقدار $PATH_INFO را روی /abcd و مقدار $QUERY_STRING را روی defgh=ijkl تنظیم خواهد کرد.

نکات بیشتر درباره پردازش مسیرهای CGI:

  • نشانی باید کدر (opaque) باشد، بنابراین نباید بعد از طرح‌واره (scheme) دو اسلش اضافه کنید. به عنوان مثال cgi-bin://script-name کار نخواهد کرد و فقط cgi-bin:script-name معتبر است.
  • مسیرهایی که با /cgi-bin/ یا /$LIB/ شروع می‌شوند به‌طور خودکار این بخش از آن‌ها حذف می‌شود. بنابراین برای نمونه cgi-bin:/cgi-bin/script-name به cgi-bin:script-name تبدیل می‌شود.
  • اگر مقدار external.w3m-cgi-compat برابر با true باشد، نشانی‌های file: در صورتی که نام مسیر با /cgi-bin/، /$LIB/ یا مسیر یک اسکریپت CGI محلی شروع شود، به نشانی‌های cgi-bin: تبدیل می‌شوند. نکته: این رفتار ناامن است؛ لطفاً از آن استفاده نکنید مگر آنکه واقعاً نیاز باشد.
  • مسیرهای مطلق نیز پذیرفته می‌شوند، مانند cgi-bin:/path/to/cgi/dir/script-name. با این حال توجه داشته باشید که این حالت تنها زمانی کار می‌کند که /path/to/cgi/dir از قبل به عنوان یک دایرکتوری CGI در external.cgi-dir تعیین شده باشد.

اسکریپت‌های CGI محلی ممکن است سرآیندهایی ارسال کنند که Chawan آن‌ها را به‌طور ویژه تفسیر می‌کند (و بنابراین آن‌ها را به عنوان مثال به fetch API و غیره هدایت نخواهد کرد):

  • Status: به عنوان کد وضعیت HTTP تفسیر می‌شود.
  • Cha-Control: سرآیند ویژه، به توضیحات زیر مراجعه کنید.

این سرآیندها باید پیش از هرگونه سرآیند عادی ارسال شوند. سرآیندهایی که پس از یک سرآیند عادی یا سرآیند Cha-Control: ControlDone دریافت شوند، به عنوان سرآیندهای عادی در نظر گرفته می‌شوند.

مقدار سرآیند Cha-Control به صورت زیر تجزیه می‌شود:

Cha-Control-Value = Command *Parameter
Command = ALPHA *ALPHA
Parameter = SPACE *CHAR

به عبارت دیگر ساختار آن به صورت Command [Param1] [Param2] ... است.

دستورات در دسترس فعلی عبارتند از:

  • Connected: هیچ پارامتری نمی‌پذیرد. باید نخستین سرآیند گزارش‌شده باشد؛ این نشان می‌دهد که اتصال به سرور با موفقیت برقرار شده، اما هنوز داده‌ای دریافت نشده است. هنگامی که هر سرآیند دیگری پیش از آن ارسال شود، Chawan به‌گونه‌ای عمل می‌کند که گویی سرآیند Cha-Control: Connected پیش از آن به‌طور ضمنی ارسال شده است.
  • ConnectionError: باید نخستین سرآیند گزارش‌شده باشد. پارامتر ۱ کد خطا است، به ادامه مراجعه کنید. اگر هرگونه پارامتر بعدی داده شود، آن‌ها به هم متصل می‌شوند تا یک پیام خطای سفارشی را تشکیل دهند.

نکته: پیام‌های خطای کوتاه اما گویا ترجیح داده می‌شوند؛ پیام‌هایی که در صفحه جا نمی‌شوند در حال حاضر کوتاه (truncate) می‌شوند.

•
ControlDone: نشان می‌دهد که دیگر هیچ سرآیند ویژه‌ای ارسال نخواهد شد؛ این بدان معناست که سرآیندهای Cha-Control و Status که پس از این ارسال شوند باید به عنوان سرآیندهای عادی تفسیر گردند (و بنابراین به عنوان مثال برای کدهای جاوااسکریپتی که با استفاده از fetch API اسکریپت را فراخوانی می‌کنند در دسترس خواهند بود).

هشدار: این سرآیند باید پیش از هر سرآیند غیر کدگذاری‌شده‌ثابت که ورودی خارجی دریافت می‌کند ارسال شود. برای مثال، یک کلاینت HTTP باید پیش از بازگرداندن سرآیندهای دریافتی، Cha-Control: ControlDone را ارسال کند.

در ادامه فهرستی از کدهای خطا و معادل‌های رشته‌ای آن‌ها آمده است. اسکریپت‌های CGI می‌توانند از هر یک (اما نه هر دو) در یک سرآیند ConnectionError استفاده کنند.

  • 1 InternalError: یک خطای داخلی مانع از بازیابی منبع درخواستی توسط اسکریپت شد. اسکریپت‌های CGI همچنین می‌توانند از این کد استفاده کنند تا نشان دهند هیچ اطلاعی از علت بروز خطا ندارند.
  • 2 InvalidMethod: کلاینت داده‌ها را با استفاده از متدی درخواست کرده که توسط این پروتکل پشتیبانی نمی‌شود.
  • 3 InvalidURL: نشانی وب درخواستی نتوانست به عنوان یک نشانی وب معتبر برای این قالب تفسیر شود.
  • 4 FileNotFound: هیچ فایلی در نشانی درخواستی یافت نشد، بنابراین درخواست بی‌معنی است. نکته: این مورد فقط باید توسط پروتکل‌هایی استفاده شود که متکی به معماری کلاینت-سرور نیستند، مانند دسترسی به فایل محلی، پایگاه‌های داده محلی یا سازوکارهای همتابه‌همتا (P2P) بازیابی فایل. پاسخ سرور با “no file found” یک خطای اتصال نیست و بهتر است به عنوان پاسخی با کد وضعیت 404 نشان داده شود.
  • 5 ConnectionRefused: سرور از برقراری اتصال خودداری کرد.
  • 6 ProxyRefusedToConnect: پروکسی از برقراری اتصال خودداری کرد.
  • 7 FailedToResolveHost: نام میزبان نتوانست تحلیل (resolve) شود.
  • 8 FailedToResolveProxy: پروکسی نتوانست تحلیل (resolve) شود.
  • 9 ProxyAuthFail: پروکسی نام کاربری/گذرواژه ارائه‌شده را رد کرد.
  • 10 InvalidResponse: پاسخ سرور به قدری با مشخصات مغایرت دارد که پردازش معنادار آن امکان‌پذیر نیست.
  • 11 ProxyInvalidResponse: پاسخ پروکسی به قدری با مشخصات مغایرت دارد که پردازش معنادار آن امکان‌پذیر نیست.

برنامه Chawan متغیرهای محیطی زیر را تنظیم می‌کند:

  • SERVER_SOFTWARE="Chawan"
  • SERVER_PROTOCOL="HTTP/1.0"
  • SERVER_NAME="localhost"
  • SERVER_PORT="80"
  • REMOTE_HOST="localhost"
  • REMOTE_ADDR="127.0.0.1"
  • GATEWAY_INTERFACE="CGI/1.1"
  • SCRIPT_NAME="/cgi-bin/script-name" در صورت فراخوانی با یک مسیر نسبی، و "/path/to/script/script-name" در صورت فراخوانی با یک مسیر مطلق.
  • SCRIPT_FILENAME="/path/to/script/script-name"
  • QUERY_STRING= رشته پرس‌وجو (یعنی URL.search). این متغیر با کدگذاری درصدی (percent-encoded) تنظیم می‌شود.
  • PATH_INFO= همه موارد بعد از نام مسیر اسکریپت، مثلاً برای cgi-bin:script-name/abcd/efgh برابر با "/abcd/efgh". این متغیر با کدگذاری درصدی کدگذاری نمی‌شود.
  • REQUEST_URI="$SCRIPT_NAME/$PATH_INFO?$QUERY_STRING
  • REQUEST_METHOD= متد HTTP استفاده‌شده برای ارسال درخواست، مانند GET یا POST
  • REQUEST_HEADERS= فهرستی جداشده با خط جدید از تمام سرآیندهای این درخواست.
  • CHA_LIBEXEC_DIR= دایرکتوری libexec که Chawan در زمان کامپایل برای استفاده از آن پیکربندی شده است. برای جزئیات درباره سودمند بودن این متغیر، بخش ابزارها را در ادامه ببینید.
  • CONTENT_TYPE= برای درخواست‌های POST، مقدار سرآیند Content-Type. برای سایر انواع درخواست (مانند GET) تنظیم نمی‌شود.
  • CONTENT_LENGTH= طول محتوا، در صورتی که $CONTENT_TYPE تنظیم شده باشد.
  • ALL_PROXY= در صورت تعیین پروکسی، نشانی پروکسی. هشدار: به دلایل امنیتی، این مورد باید هنگام برقراری ارتباطات خارجی رعایت شود. اگر یک اسکریپت CGI از پروکسی پشتیبانی نمی‌کند، در زمان تنظیم بودن متغیر ALL_PROXY هرگز نباید هیچ اتصال خارجی برقرار کند، بلکه باید یک پیام خطا بازگرداند.
  • HTTP_COOKIE= در صورت تعیین، مقدار سرآیند Cookie.
  • HTTP_REFERER= در صورت تعیین، مقدار سرآیند Referer.
  • CHA_TMP_DIR= دایرکتوری مورداستفاده برای ذخیره فایل‌های موقت.
  • CHA_DIR= مکان فایل پیکربندی.

برای درخواست‌هایی که از بازنویسی urimethodmap ناشی می‌شوند، Chawan همچنین بخش‌های تجزیه‌شده نشانی را به عنوان متغیرهای محیطی تنظیم می‌کند. استفاده از این متغیرها به شدت توصیه می‌شود تا از اکسپلویت‌های ناشی از تجزیه دوگانه نشانی‌ها جلوگیری شود.

اگر example://username:password@example.org:1234/path/name.html?example نشانی اصلی باشد، در این صورت:

  • MAPPED_URI_SCHEME= طرح‌واره نشانی اصلی، در این مورد example.
  • MAPPED_URI_USERNAME= بخش نام کاربری، در این مورد username. اگر هیچ نام کاربری مشخص نشده باشد، این متغیر روی رشته خالی تنظیم می‌شود.
  • MAPPED_URI_PASSWORD= بخش گذرواژه، در این مورد password. اگر هیچ گذرواژه‌ای مشخص نشده باشد، این متغیر روی رشته خالی تنظیم می‌شود.
  • MAPPED_URI_HOST= بخش میزبان، در این مورد host.org. اگر هیچ میزبانی مشخص نشده باشد، این متغیر روی رشته خالی تنظیم می‌شود. (نمونه‌ای از نشانی بدون میزبان: about:blank، که در اینجا blank نام مسیر است.)
  • MAPPED_URI_PORT= پورت، در این مورد 1234. اگر هیچ پورتی مشخص نشده باشد، این متغیر روی رشته خالی تنظیم می‌شود. (در این حالت، انتظار می‌رود اسکریپت CGI در صورت وجود، از پورت پیش‌فرض طرح‌واره استفاده کند.)
  • MAPPED_URI_PATH= نام مسیر، در این مورد /path/name.html?example. اگر هیچ مسیری مشخص نشده باشد، این متغیر روی رشته خالی تنظیم می‌شود. نام مسیر با کدگذاری درصدی ذخیره می‌شود.
  • MAPPED_URI_QUERY= رشته پرس‌وجو، در این مورد example. برخلاف جاوااسکریپت، علامت سؤال به ابتدای رشته افزوده نمی‌شود. رشته پرس‌وجو نیز با کدگذاری درصدی ذخیره می‌شود.

بخش قطعه (fragment) عمداً نادیده گرفته شده است.

اگر بدنه درخواست خالی نباشد، از طریق ورودی استاندارد به درون برنامه جریان می‌یابد.

توجه داشته باشید که این درخواست ممکن است از هر دو نوع application/x-www-form-urlencoded یا multipart/form-data باشد؛ متغیر CONTENT_TYPE اطلاعات مربوط به نوع درخواست و در مورد درخواست چندبخشی (multipart)، مرز (boundary) را نیز ذخیره می‌کند.

برنامه Chawan باینری‌های کمکی خاصی فراهم می‌کند که ممکن است برای اسکریپت‌های CGI سودمند باشند. این ابزارها می‌توانند با اجرای قابل‌حمل "$CHA_LIBEXEC_DIR"/[program] در دسترس قرار گیرند.

در حال حاضر، ابزارهای زیر در دسترس هستند:

  • urldec: رمزگشایی درصدی رشته‌های ارائه‌شده در ورودی استاندارد.
  • urlenc: کدگذاری درصدی رشته‌های ارائه‌شده در ورودی استاندارد، با دریافت مجموعه کدگذاری درصدی به عنوان پارامتر اول.

توجه داشته باشید که خطای استاندارد (stderr) به کنسول مرورگر هدایت می‌شود (به‌طور پیش‌فرض، M-cM-c). این قابلیت اشکال‌زدایی یک اسکریپت CGI با رفتار نادرست را آسان می‌کند، اما ممکن است در صورت ثبت بیش از حد لاگ، مرورگر را کُند سازد. اگر این رفتار مورد نظر نیست، اسکریپت خود را در قالب یک اسکریپت شل بسته‌بندی کنید که stderr را به /dev/null هدایت کند.

این بدان معناست که فراخوانی execl برای اسکریپت با شکست مواجه شده است. اطمینان حاصل کنید که بیت اجرایی اسکریپت CGI شما تنظیم شده باشد، یعنی دستور chmod +x /path/to/cgi/script را اجرا کنید.

مطمئن شوید که اسلش‌های ابتدایی اضافه نکرده‌اید. یادآوری: cgi-bin://script-name کار نمی‌کند، از cgi-bin:script-name استفاده کنید.

دوباره بررسی کنید که اسکریپت CGI شما در مکان درستی قرار داشته باشد. همچنین، مطمئن شوید که تصادفاً اسکریپت را با یک مسیر مطلق از طریق cgi-bin:/script-name (به جای حالت صحیح cgi-bin:script-name) فراخوانی نمی‌کنید.

همچنین ممکن است مقدار external.cgi-dir روی دایرکتوری واقعی که اسکریپت شما در آن است تنظیم نشده باشد. توجه داشته باشید که به‌طور پیش‌فرض، این مورد به مسیر فایل باینری وابسته است؛ بنابراین برای نمونه اگر فایل باینری شما در ~/src/chawan/target/release/bin/cha قرار دارد، اما اسکریپت CGI خود را در /usr/local/libexec/chawan/cgi-bin قرار داده‌اید، کار نخواهد کرد.

این بدان معناست که یکی از فراخوانی‌های pipe یا fork با شکست مواجه شده است. شاید با کمبود حافظه مواجه شده‌اید؟

cha(1) cha-urimethodmap(5)