سرور مجازی

۲۷ مطلب با کلمه‌ی کلیدی «سرور مجازی» ثبت شده است

  • ۰
  • ۰

نحوه به اشتراک گذاری داده ها بین Docker Container و Host

ورود به سایت

معرفی

به طور کلی ، Docker containers زودگذر هستند و درست به اندازه ای طول می کشد که دستور صادر شده در containers کامل شود. به طور پیش فرض ، هر گونه داده ایجاد شده در داخل ظرف فقط از داخل containers و فقط در حین کار در دسترس است.

از حجم های Docker می توان برای اشتراک فایل بین سیستم host و Docker container استفاده کرد. به عنوان مثال ، فرض کنید شما می خواهید از تصویر رسمی Docker Nginx استفاده کنید و یک کپی دائمی از پرونده های log Nginx برای تجزیه و تحلیل بعدی نگه دارید. به طور پیش فرض ، تصویر nginx Docker به پوشه/var/log/nginx داخل Docker Nginx container وارد می شود. به طور معمول از طریق سیستم فایل میزبان قابل دسترسی نیست.

در این آموزش ، نحوه دسترسی داده ها از Docker containers به دستگاه host را بررسی می کنیم.

پیش نیازها

برای پیگیری این مقاله ، به یک سرور اوبونتو 18.04 با موارد زیر نیاز دارید:

  • یک non-root user با امتیازات sudo ، به دنبال راه اندازی سرور اولیه با راهنمای اوبونتو 18.04.
  • Docker با دستورالعمل های مرحله 1 و مرحله 2 نحوه نصب و استفاده از Docker در اوبونتو 18.04 نصب شده است.

اگر با Docker تازه کار هستید ، سری Docker Ecosystem نمای کلی مفاهیم کلیدی را ارائه می دهد.

مرحله 1 – اتصال حجم

دستور زیر یک پوشه به نام nginxlogs در فهرست اصلی کاربر فعلی شما ایجاد کرده و آن را به/var/log/nginx در ظرف متصل می کند:

docker run –name=nginx -d -v ~/nginxlogs:/var/log/nginx -p 5000:80 nginx

بیایید کمی وقت بگذاریم تا این دستور را با جزئیات بررسی کنیم:

  • –name = nginx ، container را نامگذاری می کند تا بتوانیم راحت تر به آن مراجعه کنیم.
  • -d فرآیند را جدا کرده و در پس زمینه اجرا می کند. در غیر این صورت ، ما فقط یک پیام خالی Nginx را مشاهده می کنیم و تا زمانی که Nginx را نکشیم ، نمی توانیم از این ترمینال استفاده کنیم.
  • v ~/nginxlogs:/var/log/nginx یک حجم bindmount ایجاد می کند که فهرست/var/log/nginx را از داخل ظرف Nginx به فهرست ~/nginxlogs در دستگاه میزبان پیوند می دهد. داکر از a: برای تقسیم مسیر میزبان از مسیر ظرف استفاده می کند و مسیر میزبان همیشه اول است.
  • -p 5000: 80 یک پورت رو به جلو ایجاد می کند. Nginx container به طور پیش فرض روی پورت 80 گوش می دهد. این پرچم پورت ظرف 80 را به پورت 5000 در سیستم میزبان ترسیم می کند.
  • nginx مشخص می کند که container باید از تصویر Nginx ساخته شود ، که دستور nginx -g “daemon off” را برای شروع Nginx صادر می کند.

مرحله 2 – دسترسی به داده ها در میزبان

ما در حال حاضر یک نسخه از Nginx را داریم که در داخل Docker container روی دستگاه ما اجرا می شود و پورت 5000 دستگاه میزبان ما مستقیماً به آن نسخه از پورت 80 Nginx ترسیم می شود.

آدرس را در مرورگر وب با استفاده از آدرس IP یا نام میزبان سرور خود و شماره پورت بارگذاری کنید: http: // your_server_ip: 5000. باید ببینی:

جالبتر اینکه اگر در فهرست ~/nginxlogs در host جستجو کنیم ، access.log ایجاد شده توسط container’s nginx را مشاهده می کنیم که درخواست ما را نشان می دهد:

cat ~/nginxlogs/access.log

این باید چیزی شبیه به این نشان دهد:

 

Output

203.0.113.0 - - [11/Jul/2018:00:59:11 +0000] "GET / HTTP/1.1" 200 612 "-"
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36" "-"

در صورت ایجاد هرگونه تغییر در پوشه ~/nginxlogs ، می توانید آنها را از داخل Docker container در زمان واقعی نیز مشاهده کنید.

نتیجه

در این آموزش ما نحوه ایجاد یک حجم داده Docker برای به اشتراک گذاری اطلاعات بین یک container و سیستم host file را نشان دادیم. این در محیط های توسعه مفید است ، جایی که برای اشکال زدایی دسترسی به گزارش ها ضروری است. برای کسب اطلاعات بیشتر در مورد به اشتراک گذاری داده های مداوم بین ظروف ، به نحوه اشتراک گذاری داده ها بین Docker Containers نگاه کنید.

 

برچسب‌ها:

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه استفاده از رابط ها در TypeScript

ورود به سایت

معرفی

TypeScript افزونه ای از زبان جاوا اسکریپت است که از زمان اجرای جاوا اسکریپت با یک نوع تایپ کننده زمان کامپایل استفاده می کند.

TypeScript روش های متعددی را برای نمایش اشیاء در کد شما ارائه می دهد که یکی از آنها استفاده از رابط ها است. رابط های موجود در TypeScript دو ​​سناریو استفاده دارند: می توانید قراردادی ایجاد کنید که کلاسها باید از آن پیروی کنند ، مانند اعضایی که آن کلاسها باید اجرا کنند ، و همچنین می توانید انواع را در برنامه خود نشان دهید ، درست مانند اعلان نوع معمولی. (برای اطلاعات بیشتر در مورد انواع ، نحوه استفاده از انواع اصلی در TypeScript و نحوه ایجاد انواع سفارشی در TypeScript را بررسی کنید.)

ممکن است توجه داشته باشید که رابط ها و انواع دارای مجموعه ای از ویژگی های مشابه هستند. در واقع ، تقریباً همیشه می توان یکی را جایگزین دیگری کرد. تفاوت اصلی این است که رابط ها ممکن است بیش از یک اعلان برای یک رابط داشته باشند ، که TypeScript ادغام می شود ، در حالی که انواع را فقط یک بار می توان اعلام کرد. همچنین می توانید از انواع برای ایجاد نام مستعار از انواع اولیه (مانند رشته و بولی) استفاده کنید ، که رابط ها نمی توانند انجام دهند.

رابط های موجود در TypeScript راهی قدرتمند برای نمایش ساختارهای نوع هستند. آنها به شما امکان می دهند استفاده از آن ساختارها را ایمن کرده و به طور همزمان آنها را مستند کنید ، به طور مستقیم تجربه توسعه دهنده را بهبود می بخشد.

در این آموزش ، شما رابط هایی را در TypeScript ایجاد می کنید ، نحوه استفاده از آنها را یاد می گیرید و تفاوت بین انواع معمولی و رابط ها را درک می کنید. نمونه های مختلف کد را امتحان می کنید ، که می توانید آنها را در محیط TypeScript یا TypeScript Playground خود ، محیط آنلاین که به شما امکان می دهد TypeScript را مستقیماً در مرورگر بنویسید ، دنبال کنید.

پیش نیازها

برای پیگیری این آموزش ، شما نیاز دارید:

  • محیطی که در آن می توانید برنامه های TypeScript را اجرا کنید تا همراه با مثال ها دنبال کنید. برای تنظیم این دستگاه در دستگاه محلی خود ، به موارد زیر نیاز دارید.
    • هر دو Node و npm (یا نخ) به منظور اجرای یک محیط توسعه که بسته های مربوط به TypeScript را مدیریت می کند ، نصب شده است. این آموزش با Node.js نسخه 14.3.0 و npm نسخه 6.14.5 آزمایش شده است. برای نصب روی macOS یا اوبونتو 18.04 ، مراحل نحوه نصب Node.js و ایجاد محیط توسعه محلی در macOS یا قسمت Installing using a PPA از نحوه نصب Node.js در اوبونتو 18.04 را دنبال کنید. اگر از زیر سیستم Windows برای Linux (WSL) استفاده می کنید ، این نیز کار می کند.
    • علاوه بر این ، به TypeScript Compiler (tsc) نصب شده بر روی دستگاه خود نیاز دارید.
  • شما به دانش کافی از جاوا اسکریپت ، به ویژه نحو ES6+ ، مانند تخریب ، عملگرهای استراحت و واردات/صادرات نیاز دارید. اگر به اطلاعات بیشتری در مورد این موضوعات نیاز دارید ، خواندن نحوه کدگذاری در سری JavaScript توصیه می شود.
  • این آموزش به جنبه های ویرایشگرهای متنی که از TypeScript پشتیبانی می کنند اشاره می کند و خطاهای خطی را نشان می دهد. این برای استفاده از TypeScript ضروری نیست ، اما از ویژگیهای TypeScript بیشتر استفاده می کند. برای بهره مندی از این موارد ، می توانید از ویرایشگر متنی مانند Visual Studio Code استفاده کنید که از TypeScript پشتیبانی کامل دارد. همچنین می توانید این مزایا را در TypeScript Playground امتحان کنید.

همه نمونه های نشان داده شده در این آموزش با استفاده از TypeScript نسخه 4.2.2 ایجاد شده است.

ایجاد و استفاده از رابط ها در TypeScript

در این بخش ، رابط هایی را با استفاده از ویژگی های مختلف موجود در TypeScript ایجاد خواهید کرد. همچنین نحوه استفاده از رابط های ایجاد شده را خواهید آموخت.

رابط ها در TypeScript با استفاده از کلید واژه رابط و سپس نام رابط و سپس یک بلوک {} با بدنه رابط ایجاد می شوند. به عنوان مثال ، در اینجا یک رابط Logger است:

interface Logger {
  log: (message: string) => void;
}

مشابه ایجاد یک نوع معمولی با استفاده از اعلان نوع ، فیلدهای نوع و نوع آنها را در {} مشخص می کنید:

interface Logger {
  log: (message: string) => void;
}

رابط Logger نشان دهنده یک شی است که دارای یک ویژگی واحد به نام log است. این ویژگی یک تابع است که یک پارامتر واحد از نوع string را می پذیرد و void را برمی گرداند.

می توانید از رابط Logger به عنوان هر نوع دیگری استفاده کنید. در اینجا یک مثال ایجاد یک شیء تحت اللفظی مطابق با رابط Logger آورده شده است:

interface Logger {
  log: (message: string) => void;
}

const logger: Logger = {
  log: (message) => console.log(message),
};

مقادیری که از رابط Logger به عنوان نوع خود استفاده می کنند باید دارای اعضایی مشابه اعلان رابط Logger باشند. اگر برخی از اعضا اختیاری باشند ، ممکن است حذف شوند.

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

interface Logger {
  log: (message: string) => void;
}

const logger: Logger = {
  log: (message) => console.log(message),
  otherProp: true,
};

در این حالت ، کامپایلر TypeScript خطای 2322 را منتشر می کند ، زیرا این ویژگی در اعلان رابط Logger وجود ندارد:

 

Output

Type '{ log: (message: string) => void; otherProp: boolean; }' is not assignable to type 'Logger'.
  Object literal may only specify known properties, and 'otherProp' does not exist in type 'Logger'. (2322)

نوع دیگر Extending

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

تصور کنید یک رابط کاربری قابل پاک کردن دارید ، مانند این یکی:

interface Clearable {
  clear: () => void;
}

سپس می توانید یک رابط جدید ایجاد کنید که از آن گسترش یافته و همه زمینه های آن را به ارث برده است. در مثال زیر ، رابط Logger در حال گسترش از رابط Clearble است. به خطوط برجسته توجه کنید:

interface Clearable {
  clear: () => void;
}

interface Logger extends Clearable {
  log: (message: string) => void;
}

رابط Logger هم اکنون دارای یک عضو واضح است که یک تابع است که هیچ پارامتری را نمی پذیرد و void را برمی گرداند. این عضو جدید از رابط Clearable به ارث برده شده است. مثل این است که ما این کار را کرده ایم:

interface Logger {
  log: (message: string) => void;
  clear: () => void;
}

هنگام نوشتن تعداد زیادی رابط با مجموعه ای از زمینه های مشترک ، می توانید آنها را در یک رابط مختلف استخراج کرده و رابط های خود را تغییر دهید تا از رابط جدیدی که ایجاد کرده اید گسترش یابد.

برای بازگشت به مثال Clearble که قبلاً استفاده شد ، تصور کنید که برنامه شما نیاز به رابط متفاوتی دارد ، مانند رابط StringList زیر ، برای نشان دادن یک ساختار داده که دارای چندین رشته است:

interface StringList {
  push: (value: string) => void;
  get: () => string[];
}

با گسترش این رابط StringList جدید ، رابط Clearable موجود را گسترش می دهید ، شما مشخص می کنید که این رابط همچنین اعضایی را در رابط Clearable تنظیم کرده است و ویژگی روشن را به تعریف نوع رابط StringList اضافه می کند:

interface StringList extends Clearable {
  push: (value: string) => void;
  get: () => string[];
}

رابط ها می توانند از هر نوع شیء مانند رابط ها ، انواع معمولی و حتی کلاس ها گسترش یابند.

رابط هایی با امضای قابل تماس

اگر رابط نیز قابل تماس باشد (یعنی یک تابع نیز باشد) ، می توانید با ایجاد یک امضای قابل تماس ، این اطلاعات را در اعلان رابط منتقل کنید.

یک امضای قابل تماس با افزودن یک اعلان تابع در داخل رابط که به هیچ عضوی متصل نیست و با استفاده از: به جای => هنگام تنظیم نوع بازگشتی تابع ، ایجاد می شود.

به عنوان مثال ، یک امضای قابل تماس به رابط Logger خود اضافه کنید ، مانند کد برجسته زیر:

interface Logger {
  (message: string): void;
  log: (message: string) => void;
}

توجه داشته باشید که امضای قابل تماس شبیه به اعلان نوع یک تابع ناشناس است ، اما در نوع بازگشتی که استفاده می کنید: به جای =>. این بدان معناست که هر مقدار مقید به نوع رابط Logger می تواند مستقیماً به عنوان یک تابع فراخوانی شود.

برای ایجاد مقداری که با رابط Logger شما مطابقت داشته باشد ، باید الزامات رابط را در نظر بگیرید:

  1. باید قابل تماس باشد.
  2. باید دارای یک ویژگی به نام log باشد که یک تابع است که یک پارامتر رشته را قبول می کند.

بیایید متغیری به نام logger ایجاد کنیم که می تواند به نوع رابط Logger شما اختصاص داده شود:

interface Logger {
  (message: string): void;
  log: (message: string) => void;
}

const logger: Logger = (message: string) => {
  console.log(message);
}
logger.log = (message: string) => {
  console.log(message);
}

برای مطابقت با رابط Logger ، مقدار باید قابل تماس باشد ، به همین دلیل است که متغیر logger را به یک تابع اختصاص می دهید:

interface Logger {
  (message: string): void;
  log: (message: string) => void;
}

const logger: Logger = (message: string) => {
  console.log(message);
}
logger.log = (message: string) => {
  console.log(message);
}

سپس ویژگی log را به تابع logger اضافه می کنید:

interface Logger {
  (message: string): void;
  log: (message: string) => void;
}

const logger: Logger = (message: string) => {
  console.log(message);
}
logger.log = (message: string) => {
  console.log(message);
}

این توسط رابط Logger مورد نیاز است. مقادیر متصل به رابط Logger نیز باید دارای ویژگی log باشند که تابعی است که یک پارامتر یک رشته را می پذیرد و void را برمی گرداند.

اگر ویژگی log را وارد نکرده باشید ، کامپایلر TypeScript خطای 2741 را به شما می دهد:

 

Output

Property 'log' is missing in type '(message: string) => void' but required in type 'Logger'. (2741)

اگر ویژگی log در متغیر logger دارای امضای نوع ناسازگار باشد ، مانند تنظیم آن روی true ، خطای مشابهی را منتشر می کند:

interface Logger {
  (message: string): void;
  log: (message: string) => void;
}


const logger: Logger = (message: string) => {
  console.log(message);
}
logger.log = true;

در این مورد ، کامپایلر TypeScript خطای 2322 را نشان می دهد:

 

Output

Type 'boolean' is not assignable to type '(message: string) => void'. (2322)

یکی از ویژگیهای خوب تنظیم متغیرها برای داشتن یک نوع خاص ، در این مورد تنظیم متغیر logger برای نوع رابط Logger ، این است که TypeScript اکنون می تواند نوع پارامترهای عملکرد logger و عملکرد در log را استنباط کند. ویژگی.

با حذف اطلاعات نوع از آرگومان هر دو تابع ، می توانید آن را بررسی کنید. توجه داشته باشید که در کد برجسته زیر ، پارامترهای پیام یک نوع ندارند:

interface Logger {
  (message: string): void;
  log: (message: string) => void;
}


const logger: Logger = (message) => {
  console.log(message);
}
logger.log = (message) => {
  console.log(message);
}

و در هر دو مورد ، ویرایشگر شما هنوز باید بتواند نشان دهد که نوع پارامتر یک رشته است ، زیرا این نوع مورد انتظار رابط Logger است.

رابط با امضای فهرست

شما می توانید یک امضای فهرست به رابط کاربری خود اضافه کنید ، درست مانند انواع معمولی ، بنابراین به رابط اجازه می دهد تا تعداد نامحدودی از ویژگی ها را داشته باشد.

به عنوان مثال ، اگر می خواهید یک رابط DataRecord ایجاد کنید که دارای تعداد نامحدود فیلد رشته است ، می توانید از امضای فهرست برجسته زیر استفاده کنید:

interface DataRecord {
  [key: string]: string;
}

سپس می توانید از رابط DataRecord برای تعیین نوع هر شیئی که دارای پارامترهای متعدد رشته نوع است استفاده کنید:

interface DataRecord {
  [key: string]: string;
}

const data: DataRecord = {
  fieldA: "valueA",
  fieldB: "valueB",
  fieldC: "valueC",
  // ...
};

در این بخش ، با استفاده از ویژگی های مختلف موجود در TypeScript ، رابط هایی ایجاد کردید و نحوه استفاده از رابط هایی را که ایجاد کردید آموختید. در بخش بعدی ، با تفاوت بین اعلان های نوع و رابط بیشتر آشنا می شوید و با ادغام اعلانات و افزایش ماژول تمرین می کنید.

تفاوت بین Types and Interfaces

تا کنون ، مشاهده کرده اید که اعلان رابط و اعلامیه مشابه هستند و تقریباً مجموعه ای از ویژگی ها را دارند.

به عنوان مثال ، شما یک رابط Logger ایجاد کرده اید که از یک رابط Clearble توسعه یافته است:

interface Clearable {
  clear: () => void;
}

interface Logger extends Clearable {
  log: (message: string) => void;
}

نمایش نوع یک را می توان با استفاده از دو نوع اعلان تکرار کرد:

type Clearable = {
  clear: () => void;
}

type Logger = Clearable & {
  log: (message: string) => void;
}

همانطور که در بخشهای قبلی نشان داده شد ، اعلان رابط می تواند برای نمایش انواع اشیاء ، از توابع گرفته تا اشیاء پیچیده با تعداد نامحدودی از ویژگی ها استفاده شود. این امر با اعلانات نوع ، حتی از انواع دیگر امکان پذیر است ، زیرا شما می توانید چندین نوع را با استفاده از عملگر تقاطع و با یکدیگر قطع کنید.

از آنجا که اعلانات نوع و اعلان های رابط بسیار شبیه هستند ، باید ویژگی های خاص منحصر به فرد هر یک را در نظر بگیرید و در پایگاه کد خود سازگار باشید. یکی را برای ایجاد نمایندگی های نوع در پایگاه کد خود انتخاب کنید و فقط زمانی از ویژگی دیگر استفاده کنید که به ویژگی خاصی که فقط در دسترس آن است نیاز داشته باشید.

به عنوان مثال ، اعلان نوع دارای چند ویژگی است که اعلان رابط فاقد آن است ، مانند:

  • انواع اتحادیه
  • انواع نقشه برداری شده
  • نام مستعار به انواع اولیه

یکی از ویژگی هایی که فقط برای اعلان رابط موجود است ادغام اعلامیه است که در قسمت بعدی با آن آشنا خواهید شد. توجه به این نکته ضروری است که ادغام اظهارنامه ممکن است مفید باشد اگر شما در حال نوشتن کتابخانه هستید و می خواهید به کاربران کتابخانه قدرت گسترش انواع ارائه شده توسط کتابخانه را بدهید ، زیرا این امر با اعلانات نوع امکان پذیر نیست.

اعلامیه ادغام

TypeScript می تواند چندین اظهارنامه را در یک واحد ادغام کند و به شما این امکان را می دهد که چندین اظهارنامه را برای یک ساختار داده یکسان بنویسید و آنها را در طول کامپایلر توسط کامپایلر TypeScript به هم متصل کرده و گویی یک نوع واحد هستند. در این بخش خواهید دید که چگونه این کار می کند و چرا هنگام استفاده از رابط ها مفید است.

رابط های TypeScript را می توان دوباره باز کرد. یعنی چندین اعلان از یک رابط یکسان می توانند ادغام شوند. این زمانی مفید است که می خواهید زمینه های جدیدی را به یک رابط موجود اضافه کنید.

به عنوان مثال ، تصور کنید که یک رابط به نام DatabaseOptions مانند زیر دارید:

interface DatabaseOptions {
  host: string;
  port: number;
  user: string;
  password: string;
}

از این رابط برای انتقال گزینه ها هنگام اتصال به پایگاه داده استفاده می شود.

بعداً در کد ، یک رابط با همان نام اما با یک رشته رشته به نام dsnUrl اعلام می کنید ، مانند این:

interface DatabaseOptions {
  dsnUrl: string;
}

وقتی کامپایلر TypeScript شروع به خواندن کد شما می کند ، تمام اعلانات رابط DatabaseOptions را در یک واحد ادغام می کند. از نظر کامپایلر TypeScript ، DatabaseOptions در حال حاضر:

interface DatabaseOptions {
  host: string;
  port: number;
  user: string;
  password: string;
  dsnUrl: string;
}

رابط شامل تمام زمینه هایی است که ابتدا اعلام کرده اید ، به علاوه فیلد جدید dsnUrl که به طور جداگانه اعلام کرده اید. هر دو اعلامیه ادغام شده اند.

افزایش ماژول

ادغام بیانیه زمانی مفید است که نیاز به افزایش ماژول های موجود با ویژگی های جدید داشته باشید. یک مورد استفاده برای آن زمانی است که شما فیلدهای بیشتری را به ساختار داده ارائه شده توسط یک کتابخانه اضافه می کنید. این نسبتاً با کتابخانه Node.js به نام express رایج است ، که به شما امکان می دهد سرورهای HTTP ایجاد کنید.

هنگام کار با اکسپرس ، یک درخواست و یک شیء پاسخ به کنترل کننده های درخواست شما ارسال می شود (توابع مسئول ارائه پاسخ به درخواست HTTP). شیء درخواست معمولاً برای ذخیره داده های خاص یک درخواست خاص استفاده می شود. به عنوان مثال ، می توانید از آن برای ذخیره کاربر ثبت شده که درخواست اولیه HTTP کرده است استفاده کنید:

const myRoute = (req: Request, res: Response) => {
  res.json({ user: req.user });
}

در اینجا ، کنترل کننده درخواست json را با کلاینت کاربر روی کاربر ثبت شده به مشتری ارسال می کند. کاربر ثبت شده در مکان دیگری از کد به شی درخواست اضافه می شود ، با استفاده از یک واسطه سریع مسئول احراز هویت کاربر.

تعاریف نوع برای رابط درخواست بدون فیلد کاربر است ، بنابراین کد بالا خطای 2339 را نشان می دهد:

Property 'user' does not exist on type 'Request'. (2339)

برای رفع این مشکل ، باید یک ماژول برای بسته اکسپرس ایجاد کنید و از ادغام اعلان برای افزودن یک ویژگی جدید به رابط درخواست استفاده کنید.

اگر نوع شیء Request را در اعلان نوع express بررسی کنید ، متوجه می شوید که یک رابط اضافه شده در داخل یک فضای نام عمومی به نام Express است ، همانطور که در اسناد مخزن DefinitelyTyped نشان داده شده است:

declare global {
    namespace Express {
        // These open interfaces may be extended in an application-specific manner via declaration merging.
        // See for example method-override.d.ts (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/method-override/index.d.ts)
        interface Request {}
        interface Response {}
        interface Application {}
    }
}

برای استفاده از افزودن ماژول برای افزودن یک ویژگی جدید به رابط درخواست ، باید همان ساختار را در یک فایل اعلان نوع محلی تکرار کنید. به عنوان مثال ، تصور کنید که شما یک فایل با نام express.d.ts مانند فایل زیر ایجاد کرده اید و سپس آن را به گزینه انواع tsconfig.json خود اضافه کرده اید:

import 'express';

declare global {
  namespace Express {
    interface Request {
      user: {
        name: string;
      }
    }
  }
}

از دیدگاه کامپایلر TypeScript ، رابط درخواست دارای یک ویژگی کاربر است که نوع آنها روی یک شیء تنظیم شده است که دارای یک ویژگی واحد به نام name of type string است. این اتفاق می افتد زیرا همه اعلان ها برای یک رابط یکسان ادغام می شوند.

فرض کنید شما در حال ایجاد یک کتابخانه هستید و می خواهید به کاربران کتابخانه خود این امکان را بدهید که انواع ارائه شده توسط کتابخانه خود را افزایش دهند ، مانند آنچه در بالا با اکسپرس انجام دادید. در این حالت ، شما باید از اینترفیس های کتابخانه خود صادر کنید ، زیرا اظهارات نوع معمولی از افزایش ماژول پشتیبانی نمی کند.

نتیجه

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

 

برچسب‌ها:

 

 

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه تنظیم vsftpd برای راهنمای کاربر در اوبونتو 20.04

ورود به سایت

معرفی

FTP ، که مخفف عبارت File Transfer Protocol است ، یک پروتکل شبکه است که زمانی برای جابجایی فایل ها بین سرویس گیرنده و سرور به طور گسترده مورد استفاده قرار می گرفت. FTP هنوز برای پشتیبانی از برنامه های قدیمی و گردش کار با نیازهای بسیار خاص استفاده می شود. اگر انتخاب پروتکل دارید ، گزینه های مدرن را در نظر بگیرید که کارآمدتر ، ایمن تر و راحت تر برای تحویل فایل ها هستند. به عنوان مثال ، کاربران اینترنتی که مستقیماً از مرورگر وب خود با https بارگیری می کنند ، و کاربران خط فرمان که از پروتکل های امن مانند scp یا SFTP استفاده می کنند.

 

،FTP daemon،vsftpd بسیار ایمن ، یک سرور FTP برای بسیاری از سیستم های مشابه یونیکس ، از جمله لینوکس است ، و اغلب سرور پیش فرض FTP برای بسیاری از توزیع های لینوکس نیز می باشد. vsftpd برای بهینه سازی امنیت ، عملکرد و ثبات مفید است. همچنین محافظت قوی در برابر مشکلات امنیتی موجود در سایر سرورهای FTP را ارائه می دهد. vsftpd می تواند تنظیمات IPD مجازی ، پشتیبانی از رمزگذاری با ادغام SSL و موارد دیگر را مدیریت کند.

در این آموزش ، vsftpd را طوری پیکربندی می کنید که به کاربر اجازه دهد فایل ها را با استفاده از FTP با اطلاعات ورود به سیستم که توسط SSL/TLS ایمن شده اند ، در فهرست اصلی خود بارگذاری کند. شما همچنین می توانید سرور خود را با استفاده از FileZilla ، یک سرویس گیرنده FTP منبع باز ، برای آزمایش رمزگذاری TLS متصل کنید.

پیش نیازها

برای پیگیری این آموزش به موارد زیر نیاز دارید:

  • اولین چیزی که نیاز دارید یک سرور اوبونتو 20.04 ، یک کاربر غیر روت با امتیازات sudo و یک فایروال فعال است.
  • دومین چیزی که نیاز دارید FileZilla است ، یک سرویس گیرنده FTP منبع باز ، که روی دستگاه محلی شما نصب و پیکربندی شده است. این به شما امکان می دهد آزمایش کنید که آیا سرویس گیرنده می تواند از طریق TLS به سرور شما متصل شود یا خیر.

مرحله 1 – نصب vsftpd

با به روز رسانی لیست بسته های خود شروع کنید:

sudo apt update

بعد ، vsftpd daemon را نصب کنید:

sudo apt install vsftpd

پس از اتمام نصب ، فایل پیکربندی را کپی کنید تا بتوانید با پیکربندی خالی شروع کنید ، در حالی که نسخه اصلی را به عنوان پشتیبان ذخیره می کنید:

sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig

با پشتیبان گیری از پیکربندی موجود ، آماده پیکربندی فایروال هستید.

مرحله 2 – باز کردن فایروال

ابتدا وضعیت فایروال را بررسی کنید تا ببینید آیا فعال است یا خیر. اگر چنین است ، برای اطمینان از مجاز بودن ترافیک FTP ، تنظیماتی را انجام دهید تا قوانین فایروال مانع آزمایش ها نشوند.

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

sudo ufw status

این خروجی نشان می دهد که فایروال فعال است و فقط SSH از طریق موارد زیر مجاز است:

 

Output

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

ممکن است قوانین دیگری در نظر گرفته باشید یا اصلاً قوانین فایروال وجود نداشته باشد. از آنجا که فقط ترافیک SSH مجاز است ، باید قوانین مربوط به ترافیک FTP را اضافه کنید.

با باز کردن درگاه های 20 ، 21 و 990 شروع کنید تا وقتی TLS را فعال می کنید آماده شوند:

sudo ufw allow 20,21,990/tcp

سپس ، پورتهای 40000-50000 را برای محدوده پورتهای غیرفعال که در فایل پیکربندی تنظیم می کنید ، باز کنید:

sudo ufw allow 40000:50000/tcp

وضعیت فایروال خود را بررسی کنید:

sudo ufw status

خروجی قوانین فایروال شما باید به صورت زیر ظاهر شود:

 

Output

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
20,21,990/tcp              ALLOW       Anywhere
40000:50000/tcp            ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
20,21,990/tcp (v6)         ALLOW       Anywhere (v6)
40000:50000/tcp (v6)       ALLOW       Anywhere (v6)

با vsftpd نصب شده و پورت های لازم باز شده ، اکنون زمان ایجاد یک کاربر اختصاصی FTP است.

مرحله 3 – تهیه راهنمای کاربر

در این مرحله ، شما یک کاربر FTP اختصاصی ایجاد می کنید. با این حال ، ممکن است قبلاً یک کاربر نیاز به دسترسی به FTP داشته باشید. این راهنما نحوه حفظ دسترسی کاربر فعلی به داده های وی را توضیح می دهد ، اما ، با این وجود ، توصیه می کنیم تا قبل از پیکربندی مجدد هر کاربر موجود ، از یک کاربر اختصاصی FTP جدید استفاده کنید.

با افزودن یک کاربر آزمایشی شروع کنید:

sudo adduser sammy

FTP عموماً وقتی کاربران به یک فهرست خاص محدود می شوند از امنیت بیشتری برخوردار است. vsftpd این کار را با زندان های chroot انجام می دهد. هنگامی که chroot برای کاربران محلی فعال است ، به طور پیش فرض به فهرست اصلی آنها محدود می شود. از آنجا که vsftpd دایرکتوری را به روش خاصی ایمن می کند ، نباید توسط کاربر قابل نوشتن باشد. این برای کاربر جدیدی که فقط باید از طریق FTP متصل شود خوب است ، اما اگر یک کاربر فعلی دسترسی به پوسته را داشته باشد ، ممکن است لازم باشد در پوشه اصلی خود بنویسد.

در این مثال ، به جای حذف امتیازهای نوشتن از فهرست اصلی ، یک دایرکتوری ftp ایجاد کنید تا به عنوان chroot و یک فهرست فایلهای قابل نوشتن برای نگهداری فایلهای واقعی باشد.

ایجاد پوشه ftp:

sudo mkdir /home/sammy/ftp

مالکیت آن را تعیین کنید:

sudo chown nobody:nogroup /home/sammy/ftp

حذف مجوزهای نوشتن:

sudo chmod a-w/home/sammy/ftp

مجوزها را تأیید کنید:

sudo ls -la /home/sammy/ftp

 

Output

total 8
dr-xr-xr-x 2 nobody nogroup 4096 Sep 14 20:28 .
drwxr-xr-x 3 sammy sammy  4096 Sep 14 20:28 ..

بعد ، دایرکتوری بارگذاری فایل را ایجاد کنید:

sudo mkdir /home/sammy/ftp/files

سپس مالکیت را به کاربر اختصاص دهید:

sudo chown sammy:sammy /home/sammy/ftp/files

یک بررسی مجوز در فهرست ftp باید خروجی زیر را بازگرداند:

sudo ls -la /home/sammy/

 

Output

total 12
dr-xr-xr-x 3 nobody nogroup 4096 Sep 14 20:30 .
drwxr-xr-x 3 sammy sammy  4096 Sep 14 20:28 ..
drwxr-xr-x 2 sammy sammy  4096 Sep 14 20:30 files

در نهایت ، یک فایل test.txt اضافه کنید تا از آن برای آزمایش استفاده کنید:

echo “vsftpd test file” | sudo tee /home/sammy/ftp/files/test.txt

 

Output

vsftpd test file

اکنون که دایرکتوری ftp را ایمن کرده اید و به کاربر اجازه دسترسی به پوشه فایل ها را داده اید ، در مرحله بعد پیکربندی ما را اصلاح خواهید کرد.

مرحله 4 – پیکربندی دسترسی FTP

در این مرحله ، به یک کاربر واحد با حساب local shell اجازه می دهید تا با FTP ارتباط برقرار کند. دو تنظیم کلیدی برای این مورد از قبل در vsftpd.conf تنظیم شده است. این فایل را با استفاده از ویرایشگر متن دلخواه خود باز کنید. در اینجا ، ما از نانو استفاده می کنیم:

sudo nano /etc/vsftpd.conf

پس از باز کردن فایل ، تأیید کنید که دستورالعمل anonymous_enable روی NO و دستورالعمل local_enable روی YES تنظیم شده است:

/etc/vsftpd.conf

. . .
# Allow anonymous FTP? (Disabled by default).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
local_enable=YES
. . .

این تنظیمات از ورود به سیستم ناشناس جلوگیری می کند و به ترتیب اجازه ورود به سیستم محلی را می دهد. به خاطر داشته باشید که فعال کردن ورود به سیستم محلی به این معنی است که از هر کاربر عادی که در فایل /etc /passwd ذکر شده است می توانید برای ورود استفاده کنید.

برخی از دستورات FTP به کاربران امکان می دهد فایلها و فهرستهای موجود در سیستم فایل را اضافه ، تغییر یا حذف کنند. این دستورات را با اظهارنظر درباره تنظیمات write_enable فعال کنید. شما می توانید این کار را با حذف علامت پوند (#) قبل از این دستورالعمل انجام دهید:

/etc/vsftpd.conf

. . .
write_enable=YES
. . .

در مرحله بعد ، یک دستور user_sub_token اضافه کنید که مقدار آن متغیر محیطی USER $ است. سپس یک دستورالعمل local_root اضافه کنید و آن را در مسیری که نشان داده شده است ، اضافه کنید ، که شامل متغیر محیط USER $ نیز می شود. این تنظیم تضمین می کند که پیکربندی به این کاربر و کاربران آینده اجازه می دهد تا هنگام ورود به فهرست اصلی کاربر مناسب هدایت شوند. این تنظیمات را در هر نقطه از فایل اضافه کنید:

/etc/vsftpd.conf

. . .
user_sub_token=$USER
local_root=/home/$USER/ftp

محدوده پورت هایی را که می توانند برای FTP منفعل استفاده شوند محدود کنید تا مطمئن شوید اتصالات کافی در دسترس هستند:

/etc/vsftpd.conf

. . .
pasv_min_port=40000
pasv_max_port=50000

برای اجازه دسترسی FTP به صورت موردی ، پیکربندی را طوری تنظیم کنید که کاربران فقط زمانی که به صراحت به لیست اضافه می شوند ، دسترسی داشته باشند نه به طور پیش فرض:

/etc/vsftpd.conf

. . .
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO

userlist_deny منطق را تغییر می دهد: وقتی روی YES تنظیم شود ، دسترسی کاربران FTP به FTP ممنوع است. وقتی روی NO تنظیم شود ، فقط به کاربران موجود در لیست اجازه دسترسی داده می شود.

پس از اتمام اعمال تغییرات ، فایل را ذخیره کرده و از ویرایشگر خارج شوید. اگر از nano برای ویرایش فایل استفاده کرده اید ، می توانید این کار را با فشار دادن CTRL + X ، Y و سپس ENTER انجام دهید.

در نهایت ، کاربر خود را به /etc/vsftpd.userlist اضافه کنید. برای ضمیمه کردن فایل از پرچم -a استفاده کنید:

echo “sammy” | sudo tee -a /etc/vsftpd.userlist

بررسی کنید که طبق انتظار شما اضافه شده است:

cat /etc/vsftpd.userlistcat /etc/vsftpd.userlist

 

Output

sammy

برای بارگیری تغییرات پیکربندی ، daemon را مجدداً راه اندازی کنید:

sudo systemctl restart vsftpd

با پیکربندی موجود ، اکنون می توانید دسترسی FTP را آزمایش کنید.

مرحله 5 – آزمایش دسترسی FTP

ما سرور را طوری پیکربندی کرده ایم که فقط کاربر sammy بتواند از طریق FTP متصل شود. اکنون ما مطمئن می شویم که این کار مطابق انتظار انجام می شود.

از آنجا که دسترسی ناشناس را غیرفعال کرده اید ، می توانید با تلاش برای اتصال ناشناس آن را آزمایش کنید. اگر پیکربندی به درستی تنظیم شده باشد ، از کاربران ناشناس باید اجازه گرفته نشود. پنجره ترمینال دیگری را باز کرده و دستور زیر را اجرا کنید. حتماً آدرس IP عمومی سرور خود را 203.0.113.0 جایگزین کنید:

ftp -p 203.0.113.0

وقتی از شما نام کاربری خواسته شد ، سعی کنید به عنوان یک کاربر ناشناس مانند ناشناس وارد شوید و خروجی زیر را دریافت خواهید کرد:

 

Output

Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): anonymous
530 Permission denied.
ftp: Login failed.
ft

بستن اتصال:

bye

کاربران غیر از sammy نیز نباید در اتصال متصل شوند. سعی کنید به عنوان کاربر sudo خود متصل شوید. همچنین باید دسترسی آنها به آنها ممنوع شود و این امر باید قبل از اجازه ورود رمز عبور آنها رخ دهد:

ftp -p 203.0.113.0

 

Output

Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sudo_user
530 Permission denied.
ftp: Login failed.
ftp>

بستن ارتباط:

bye

از طرف دیگر ، کاربر sammy باید بتواند فایلها را متصل کرده ، بخواند و بنویسد. اطمینان حاصل کنید که کاربر FTP تعیین شده شما می تواند متصل شود:

ftp -p 203.0.113.0

 

Output

Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sammy
331 Please specify the password.
Password: your_user's_password
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>

اکنون به فهرست پرونده ها تغییر دهید:

cd files

 

Output

250 Directory successfully changed.

بعد ، get را برای انتقال فایل آزمایشی که قبلاً ایجاد کرده اید به دستگاه محلی خود اجرا کنید:

get test.txt

 

Output

227 Entering Passive Mode (203,0,113,0,169,12).
150 Opening BINARY mode data connection for test.txt (17 bytes).
226 Transfer complete.
17 bytes received in 0.00 secs (4.5496 kB/s)
ftp>

بعد ، فایل را با نام جدید بارگذاری کنید تا مجوزهای نوشتن را آزمایش کنید:

put test.txt upload.txt

 

Output

227 Entering Passive Mode (203,0,113,0,164,71).
150 Ok to send data.
226 Transfer complete.
17 bytes sent in 0.00 secs (5.3227 kB/s)

بستن اتصال:

bye

اکنون که پیکربندی خود را آزمایش کرده اید ، در مرحله بعد برای ایمن سازی بیشتر سرور خود اقداماتی را انجام دهید.

مرحله 6 – ایمن سازی معاملات

از آنجا که FTP هیچ داده ای در حال انتقال ، از جمله اطلاعات کاربری را رمزگذاری نمی کند ، می توانید TLS/SSL را برای ارائه این رمزگذاری فعال کنید. اولین قدم ایجاد گواهینامه های SSL برای استفاده با vsftpd است.

برای ایجاد گواهینامه جدید از openssl استفاده کنید و از پرچم -days برای اعتبار یکساله استفاده کنید. در همان فرمان ، یک کلید RSA خصوصی 2048 بیتی اضافه کنید. با تنظیم هر دو پرچم -keyout و -out بر روی یک مقدار ، کلید خصوصی و گواهی در یک فایل قرار می گیرند:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem

از شما خواسته می شود که اطلاعات آدرس گواهی خود را ارائه دهید. اطلاعات شخصی خود را با مقادیر برجسته شده جایگزین کنید:

 

Output

Generating a 2048 bit RSA private key
............................................................................+++
...........+++
writing new private key to '/etc/ssl/private/vsftpd.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:NY
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:vpsgol Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: your_server_ip
Email Address []:

برای کسب اطلاعات بیشتر در مورد پرچم های گواهینامه ، OpenSSL Essentials: کار با گواهینامه های SSL ، کلیدهای خصوصی و CSR ها را مطالعه کنید.

پس از ایجاد گواهینامه ها ، فایل پیکربندی vsftpd را دوباره باز کنید:

sudo nano /etc/vsftpd.conf

در انتهای فایل ، دو خط وجود دارد که با rsa_ شروع می شوند. آنها را با هر خط قبلی با علامت پوند (#) کامنت کنید:

/etc/vsftpd.conf

. . .
# rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
# rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
. . .

پس از آن خطوط ، خطوط زیر را که به گواهی و کلید خصوصی ایجاد شده اشاره می کنند ، اضافه کنید:

/etc/vsftpd.conf

. . .
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem

 

اکنون شما مجبور به استفاده از SSL خواهید شد ، که از اتصال مشتریانی که نمی توانند TLS را اداره کنند جلوگیری می کند. این امر برای اطمینان از رمزگذاری کل ترافیک ضروری است ، اما ممکن است کاربر FTP شما را مجبور به تغییر سرویس گیرنده کند. تغییر ssl_enable به YES:

/etc/vsftpd.conf

. . .
ssl_enable=YES
. . .

در مرحله بعد ، خطوط زیر را برای رد صریح اتصالات ناشناس از طریق SSL اضافه کنید و برای انتقال داده ها و ورودها به SSL نیاز دارید:

/etc/vsftpd.conf

. . .
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
. . .

سپس سرور را برای استفاده از TLS ، جانشین ترجیحی SSL ، با افزودن خطوط زیر پیکربندی کنید:

/etc/vsftpd.conf

. . .
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
. . .

در نهایت ، دو گزینه نهایی را اضافه کنید. مورد اول نیازی به استفاده مجدد از SSL ندارد زیرا می تواند بسیاری از سرویس گیرندگان FTP را خراب کند. مورد دوم به مجموعه های رمزگذاری “بالا” نیاز دارد ، که در حال حاضر به معنی طول کلیدها برابر یا بیشتر از 128 بیت است:

/etc/vsftpd.conf

. . .
require_ssl_reuse=NO
ssl_ciphers=HIGH
. . .

در اینجا نحوه نمایش این بخش از پرونده پس از انجام همه این تغییرات آمده است:

/etc/vsftpd.conf

# This option specifies the location of the RSA certificate to use for SSL
# encrypted connections.
#rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH

 

پس از اتمام کار ، فایل را ذخیره و ببندید. اگر از نانو استفاده می کنید ، می توانید با فشار دادن CTRL + X ، Y و سپس ENTER خارج شوید.

سرور را راه اندازی مجدد کنید تا تغییرات اعمال شوند:

sudo systemctl restart vsftpd

پس از اتمام کار ، فایل را ذخیره و ببندید. اگر از نانو استفاده می کنید ، می توانید با فشار دادن CTRL + X ، Y و سپس ENTER خارج شوید.

سرور را راه اندازی مجدد کنید تا تغییرات اعمال شوند:

sudo systemctl restart vsftpd

در این مرحله ، دیگر نمی توانید با یک سرویس گیرنده خط فرمان ناامن ارتباط برقرار کنید. اگر تلاش کرده اید ، پیام زیر را دریافت خواهید کرد:

 

Output

ftp -p 203.0.113.0
Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sammy
530 Non-anonymous sessions must use encryption.
ftp: Login failed.
421 Service not available, remote server has closed connection
ftp>

 

بعد ، تأیید کنید که می توانید با استفاده از یک سرویس گیرنده که از TLS پشتیبانی می کند ، مانند FileZilla ، متصل شوید.

مرحله 7 – آزمایش TLS با FileZilla

اکثر سرویس گیرندگان FTP مدرن می توانند پیکربندی شوند تا از رمزگذاری TLS استفاده کنند. برای اهداف خود ، ما نحوه ارتباط با FileZilla را به دلیل پشتیبانی از چندین پلت فرم نشان خواهیم داد. با مستندات سایر مشتریان مشورت کنید.

وقتی FileZilla را برای اولین بار باز می کنید ، نماد مدیر سایت را که در بالای کلمه Host قرار دارد ، سمت چپ ترین نماد در ردیف بالا ، پیدا کنید.

یک پنجره جدید باز خواهد شد. روی دکمه سایت جدید در گوشه سمت چپ پایین کلیک کنید:

در بخش My Sites نماد جدیدی با کلمات New Site ظاهر می شود. اکنون می توانید نام آن را بگذارید یا بعداً برگردید و از دکمه تغییر نام استفاده کنید.

قسمت Host را با نام یا آدرس IP پر کنید. در منوی کشویی Encryption ، Require expplicite FTP over TLS را انتخاب کنید.

برای Logon Type ، Ask for password را انتخاب کنید. کاربر FTP خود را در قسمت User وارد کنید:

روی دکمه Connect در پایین رابط کلیک کنید. از شما رمز عبور کاربر خواسته می شود:

برای اتصال OK را انتخاب کنید. اکنون باید با رمزگذاری TLS/SSL به سرور خود متصل شوید.

در مرحله بعد ، یک گواهی سرور به شما ارائه می شود

وقتی گواهی نامه را پذیرفتید ، روی پوشه فایلها دوبار کلیک کرده و upload.txt را به سمت چپ بکشید تا تأیید کنید که می توانید فایلها را بارگیری کنید:

پس از انجام این کار ، روی نسخه محلی راست کلیک کنید ، نام آن را به upload-tls.txt تغییر دهید و آن را به سرور بکشید تا تأیید شود که می توانید فایل ها را بارگذاری کنید:

اکنون تأیید کرده اید که می توانید فایل های SSL/TLS را به صورت ایمن و موفقیت آمیز منتقل کنید.

مرحله 8 – غیرفعال کردن دسترسی به پوسته (اختیاری)
اگر به دلیل نیازهای مشتری قادر به استفاده از TLS نیستید ، می توانید با غیرفعال کردن توانایی کاربر FTP برای ورود به هر روش دیگر ، امنیت بیشتری کسب کنید. یکی از راه های جلوگیری از آن ایجاد پوسته سفارشی است. اگرچه این هیچ گونه رمزگذاری را ارائه نمی دهد ، اما ممکن است ارزش این کار را داشته باشد تا دسترسی یک حساب آسیب دیده را به فایل هایی که توسط FTP قابل دسترسی هستند محدود کنید.

ابتدا فایلی به نام ftponly را در فهرست bin باز کنید:

sudo nano /bin/ftponly

پیامی را اضافه کنید که به کاربر توضیح می دهد چرا نمی تواند وارد سیستم شود:

/bin/ftponly

#!/bin/sh
echo "This account is limited to FTP access only."

فایل را ذخیره کرده و از ویرایشگر خارج شوید. اگر از نانو استفاده می کنید ، می توانید با فشار دادن CTRL + X ، Y و سپس ENTER خارج شوید.

سپس ، مجوزها را تغییر دهید تا فایل اجرایی شود:

sudo chmod a+x /bin/ftponly

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

sudo nano /etc/shells

در پایین اضافه کنید:

/etc/shells

. . .
/bin/ftponly

پوسته کاربر را با دستور زیر به روز کنید:

sudo usermod sammy -s /bin/ftponly

اکنون ، سعی کنید به عنوان sammy وارد سرور خود شوید:

ssh sammy@your_server_ip

پیام زیر را دریافت خواهید کرد:

 

Output

This account is limited to FTP access only.
Connection to 203.0.113.0 closed.

این تأیید می کند که کاربر دیگر نمی تواند به سرور ssh کند و فقط به دسترسی FTP محدود می شود. لطفاً توجه داشته باشید ، اگر هنگام ورود به سرور خود پیام خطایی دریافت کرده اید ، این می تواند به این معنی باشد که سرور شما احراز هویت رمز عبور را قبول نمی کند. استفاده از احراز هویت مبتنی بر رمز عبور می تواند سرور شما را در برابر حملات آسیب پذیر کند و به همین دلیل است که ممکن است بخواهید احراز هویت رمز عبور را غیرفعال کنید. اگر قبلاً احراز هویت مبتنی بر کلید SSH را پیکربندی کرده اید ، می توانید در مرحله 4 این آموزش درباره نحوه غیرفعال کردن احراز هویت رمز عبور در سرور خود اطلاعات بیشتری کسب کنید.

نتیجه

در این آموزش ، نحوه تنظیم FTP را برای کاربران با حساب محلی توضیح دادیم. اگر نیاز به استفاده از منبع احراز هویت خارجی دارید ، ممکن است بخواهید پشتیبانی vsftpd از کاربران مجازی را بررسی کنید. این مجموعه مجموعه ای غنی از گزینه ها را با استفاده از PAM ، ماژول های احراز هویت Pluggable ارائه می دهد و اگر شما کاربران را در سیستم دیگری مانند LDAP یا Kerberos مدیریت کنید ، انتخاب خوبی است.

 

 

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه ایجاد افزونه منبع سفارشی در Gatsby

ورود به سایت

معرفی

در ایجاد یک وب سایت یا برنامه ، اغلب یکی از سخت ترین کارها این است که داده ها را از منابع متعدد جمع آوری کرده و آنها را در یک خروجی یکنواخت جمع آوری کنید. یک راه رایج برای حل این مشکل استفاده از سیستم های ساخت کاملاً متفاوت برای قسمت های مختلف یک سایت است ، اما این امر گاهی پیچیدگی را افزایش می دهد در حالی که دستیابی به یکنواختی را دشوارتر می کند. اینجاست که Gatsby ، یک تولید کننده سایت استاتیک مبتنی بر داده (SSG) می تواند راه حلی ارائه دهد.

یکی از اهداف اصلی Gatsby حل این مشکل برای توسعه دهندگان است و افزونه های منبع اصلی ترین راه برای این کار هستند. افزونه منبع مجموعه ای از کد است که داده ها را از یک منبع معین وارد اکوسیستم Gatsby می کند. منابع می توانند از سیستم فایل محلی مانند فایلهای Markdown ، پایگاه های داده ، فیدهای داده منتشر شده یا حتی منابع داده از راه دور کاملاً پویا مانند API ها باشند.

در این آموزش ، شما پلاگین منبع سفارشی خود را ایجاد می کنید تا داده های جدید را از یک API دنیای واقعی به Gatsby وارد کنید. همچنین داده ها را فرمت می کنید تا در سراسر Gatsby به آنها دسترسی داشته باشید و در پایان آموزش ، یک پروژه کاری داشته باشید که HTML ایستا را از منبع داده پویای جدید شما ایجاد می کند.

پیش نیازها

قبل از شروع کار ، چند مورد را که لازم دارید در اینجا آورده ایم:

  • نصب محلی Node.js برای اجرای Gatsby و ایجاد سایت شما. روش نصب بر اساس سیستم عامل متفاوت است ، اما vpsgol دارای راهنمای Ubuntu 20.04 و macOS است و همیشه می توانید آخرین نسخه را در صفحه بارگیری رسمی Node.js پیدا کنید.
  • آشنایی با جاوا اسکریپت برای کار در Gatsby. زبان جاوا اسکریپت یک مبحث گسترده است ، اما نقطه شروع خوب ما نحوه کدگذاری در سری جاوا اسکریپت است.
  • آشنایی با API های وب ، Node.js و JSON.
  • یک پروژه جدید Gatsby، داربست از gatsby-starter-default. برای برآوردن این نیاز و ایجاد پروژه جدید Gatsbyاز ابتدا ، می توانید به مرحله 1 آموزش نحوه راه اندازی اولین وب سایت Gatsby مراجعه کنید.
  • اگر می خواهید رابط کاربری (UI) پست های خود را فراتر از آنچه در این آموزش آمده است سفارشی کنید ، با React و JSX و همچنین عناصر HTML آشنا باشید.

این آموزش روی Node.js v14.16.1 ، npm v6.14.12 ، Gatsby v3.13.0 و node-fetch v2.6.2 آزمایش شده است.

مرحله 1 – فایل های داربست و نصب وابستگی ها

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

از آنجا که این یک افزونه محلی خواهد بود ، یک دایرکتوری در پروژه Gatsby خود ایجاد کنید تا کد منبع افزونه را در زیر پوشه افزونه های سطح ریشه نگه دارید. می توانید این کار را با ایجاد پوشه به صورت دستی در مرورگر فایل خود یا از خط فرمان در ریشه پروژه با دستور mkdir انجام دهید:

mkdir -p plugins/my-custom-source-plugin

در مرحله بعد ، باید یک فایل package.json ایجاد کنید تا این دایرکتوری را به عنوان بسته Node.js با وابستگی های خاص خود علامت گذاری کنید. برای ایجاد این فایل و پیش پر کردن برخی از فیلدهای مورد نیاز ، از دستور زیر استفاده کنید:

cd plugins/my-custom-source-plugin
npm init -y

این دستور به پوشه افزونه تازه ایجاد شده شما منتقل می شود و سپس از npm init برای راه اندازی مجدد یک بسته جدید استفاده می کند. پرچم -y برخی از سوالات بی ربط به این پروژه را رد می کند و فایل package.json را با حداقل مقادیر مورد نیاز پر می کند.

اکنون که package.json وجود دارد ، می توانید وابستگی هایی را به افزونه خود اضافه کنید که کدگذاری عملکرد را آسان تر می کند. پیش بروید و تنها وابستگی اضافی مورد نیاز خود را در این آموزش ، node-fetch ، با استفاده از دستور زیر نصب کنید:

npm install node-fetch@^2

در نهایت ، فایل gatsby-node.js را ایجاد کنید که در نهایت کد اصلی افزونه منبع را در اختیار داشته باشد:

touch gatsby-node.js

اکنون که ساختار فایل را برای پشتیبانی از افزونه خود ایجاد کرده اید و وابستگی های اولیه را نصب کرده اید ، به دستورالعمل هایی برای یافتن و بارگیری افزونه خود به gatsby ادامه می دهید.

مرحله 2 – بارگیری و پیکربندی افزونه

مانند هر افزونه یا تم Gatsby ، Gatsby باید در مورد نحوه بارگیری افزونه از کجا آموزش داده شود. برای انجام این کار ، فایل پیکربندی اصلی Gatsby را ویرایش می کنید gatsby-config.js ، که در ریشه پروژه Gatsby شما قرار دارد. فایل را در ویرایشگر دلخواه خود باز کنید و خط برجسته زیر را اضافه کنید:

gatsby-config.js

module.exports = {
...
  plugins: [
    `gatsby-plugin-react-helmet`,
    `gatsby-plugin-image`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `my-custom-source-plugin`,
    `gatsby-transformer-sharp`,
...

از آنجا که کد منبع افزونه شما در فهرست افزونه ها وجود دارد ، تنها چیزی که برای بارگیری Gatsby لازم است این است که به نام زیر شاخه ای که در آن پوشه یافت می شود ، وارد شود. افزونه شما نیز در حال حاضر هیچ گزینه ای را انتخاب نمی کند ، بنابراین نیازی به ارسال شیء گزینه به آن در بلوک پیکربندی Gatsby نیست.

gatsby-config.js را ذخیره کرده و از فایل خارج شوید.

اکنون Gatsby را طوری پیکربندی کرده اید که افزونه منبع سفارشی شما را بارگذاری کند و همچنین به آن دقیقاً گفته اید که کجا باید کد منبع را پیدا کند. در مرحله بعد ، این کد منبع را برای کشیدن داده ها در زمان اجرا Node.js از منبع راه دور سفارشی خود ایجاد می کنید.

مرحله 3 – کشیدن داده های خام به Node.js

در مرحله قبل ، شما Gatsbyرا برای بارگیری و اجرای کد افزونه منبع سفارشی خود پیکربندی کرده اید ، اما برای انجام وظیفه وارد کردن داده های جدید به اکوسیستم Gatsby، هنوز باید این کد را ایجاد کنید. در این مرحله ، کدی را که این کار را انجام می دهد ، می نویسید ، داده های از راه دور را از طریق node-fetch واکشی کرده و برای استفاده در مراحل بعدی آماده می کنید.

افزونه های منبع می توانند تقریباً از هر جایی ، محلی یا از راه دور ، داده ها را جمع آوری کنند ، اما در این آموزش افزونه منبع شما به طور خاص عناوین و گزیده ای از دسته کتاب های برنامه نویسی رایانه ای در ویکی پدیا را از طریق API عمومی خود می کشد.

فایل my-custom-source-plugin/gatsby-node.js خود را در فهرست افزونه ها باز کرده و کد زیر را اضافه کنید:

plugins/my-custom-source-plugin/gatsby-node.js

const fetch = require('node-fetch').default

/**
 * Fetch a list of computer books from Wikipedia, with excerpts
 */
async function getWikiProgrammingBooks() {
  const BASE_ENDPOINT = "https://en.wikipedia.org/w/api.php?action=query&format=json&utf8=1&redirects=1";

  // Get list of books
  const listEndpoint = new URL(BASE_ENDPOINT);
  listEndpoint.searchParams.append('list', 'categorymembers');
  listEndpoint.searchParams.append("cmtitle", "Category:Computer_programming_books");
  listEndpoint.searchParams.append("cmlimit", "10");
  const listResults = await (await fetch(listEndpoint.toString())).json();


  // Extract out the page IDs from the list
  const pageIds = listResults.query.categorymembers.map((listing) => listing.pageid);

  // Fetch details for page IDs
  const extractEndpoint = new URL(BASE_ENDPOINT);
  extractEndpoint.searchParams.append("pageids", pageIds.join("|"));
  extractEndpoint.searchParams.append("prop", "extracts|info");
  extractEndpoint.searchParams.append("exintro", "");
  extractEndpoint.searchParams.append("explaintext", "");
  extractEndpoint.searchParams.append("inprop", "url");

  const bookResult = await (await fetch(extractEndpoint.toString())).json();

  return Object.values(bookResult.query.pages);
}

در این کد ، شما یک تابع قابل استفاده مجدد ایجاد کرده اید که می تواند برای بازگرداندن لیستی از کتابهای برنامه نویسی کامپیوتر ، به همراه شناسه های صفحه آنها (یک شناسه منحصر به فرد در ویکی پدیا) و گزیده ها/عصاره ها فراخوانی شود. در قسمت اول تابع ، URL API مناسب را ایجاد می کنید تا بتوانید لیست اولیه عناوین و شناسه های مربوط به یک دسته خاص (کتابهای برنامه نویسی کامپیوتر) را برای استفاده از آن استفاده کنید. از سازنده URL و رابط برای خواندن و مدیریت تغییرات پرس و جو استفاده می شود.

شما از روش واکشی از node-fetch برای درخواست GET به URL ساخته شده استفاده می کنید ، که لیستی از عناوین کتاب با شناسه های آنها را برمی گرداند. سپس این پاسخ به آرایه ای از مقادیر pageid تبدیل می شود ، سپس برای پرس و جو مجدد API ویکی پدیا استفاده می شود ، این بار درخواست استخراج و اطلاعات متای تولید شده برای شناسه صفحه داده شده. شناسه های صفحه با کاراکتر پیپ (|) به هم متصل می شوند ، زیرا API ویکی پدیا از این قالب برای پذیرش چندین شناسه از طریق یک مقدار رشته استفاده می کند.

سرانجام ، از آنجا که نتایج گزیده های صفحه به عنوان یک شیء باز می گردند و هر کتابی در شناسه خود به عنوان کلید درج شده است ، از Object.values ​​() برای حذف کلید شناسه صفحه و تبدیل نتایج به یک آرایه قبل از بازگشت آنها استفاده می کنید.

اگر خروجی این تابع را وارد کنید ، چیزی شبیه به این خواهد بود:

[
  {
    "pageid": 379671,
    "ns": 0,
    "title": "The C Programming Language",
    "extract": "The C Programming Language (sometimes termed K&R, after its authors' initials) is a computer programming book written by Brian Kernighan and Dennis Ritchie...",
    "fullurl": "https://en.wikipedia.org/wiki/The_C_Programming_Language",
    ...
  },
  ...
]

مطمئن شوید که تغییرات خود را ذخیره می کنید ، اما این فایل را باز نگه دارید زیرا در مرحله بعد کد بیشتری به آن اضافه می کنید.

در این مرحله از node-fetch برای بازیابی محتوای منبع از راه دور و نمایش آن در فایل gatsby-node.js استفاده کردید. در مرحله بعد ، محتوا را عادی می کنید زیرا از آن برای ایجاد گره های جدید Gatsby برای استفاده در کل پروژه Gatsby استفاده می کنید.

مرحله 4 – عادی سازی داده ها و ایجاد گره ها

واکشی محتوای از راه دور و آوردن آن در gatsby-node.js در مرحله قبل به این معنی نیست که اکنون در سراسر Gatsbyقابل دسترسی است. به منظور به اشتراک گذاری داده ها به صورت جهانی ، Gatsby از مفهوم گره ها استفاده می کند ، که در یک لایه داده GraphQL یکپارچه به اشتراک گذاشته می شوند. در این مرحله ، شما این گره ها را ایجاد می کنید و محتوای جدید خود را برای مطابقت قالب بندی می کنید.

اگرچه اکنون می توانید با فراخوانی getWikiProgrammingBooks () نتایج ویکی پدیا را بازیابی کرده و به آنها دسترسی پیدا کنید ، اما برای ادغام این کد با سیستم گره Gatsby، هنوز باید کد را اضافه کنید. در همان فایل gatsby-node.js مرحله قبل ، این بلوک جدید کد را برای مدیریت تولید گره ها اضافه کنید:

plugins/my-custom-source-plugin/gatsby-node.js

const fetch = require('node-fetch').default

...

exports.sourceNodes = async ({ actions, createContentDigest, createNodeId }) => {
  // Arbitrary node type constant
  const BOOK_TYPE = 'BookWikiPage';

  // Get books
  const bookResults = await getWikiProgrammingBooks();

  // Convert raw book results to nodes
  for (const book of bookResults) {
    actions.createNode({
      ...book,
      id: createNodeId(`${BOOK_TYPE}-${book.pageid}`),
      parent: null,
      children: [],
      internal: {
        type: BOOK_TYPE,
        contentDigest: createContentDigest(book)
      }
    })
  }
};

در این بلوک کد ، شما در حال تکرار هر کتابی هستید که توسط getWikiProgrammingBooks بازگردانده می شود و یک گره Gatsbyبرای آن از طریق روش createNode ایجاد می کنید. هر ویژگی و مقداری که به createNode منتقل می شود دارای اهمیت است و ارزش توجه دارد:

  • … کتاب برای گسترش جفت های کلید-مقدار از شی API ویکی پدیا در گره Gatsby که ایجاد می کنید استفاده می شود. این بدان معناست که بعداً می توانید به node.title دسترسی پیدا کنید ، زیرا از book.title کپی می شود.
  • شناسه یک ارزش جهانی منحصر به فرد در داخل Gatsby است. برای اینکه شناسه هر کتاب را در افزونه خود منحصر به فرد کنید ، باید نوع کتاب را با شناسه صفحه ویکی پدیا ترکیب کرده و یک رشته شناسه تشکیل دهید. با این حال ، از آنجا که نمی توانید مطمئن شوید سایر افزونه ها از چه شناسه هایی استفاده می کنند ، از بهترین روش ارسال شناسه خود برای ایجادNodeId استفاده کرده اید ، که یک تابع کمکی Gatsby است و تضمین می کند که شناسه به چیزی در سطح جهانی تبدیل شده است.
  • والد فیلدی است که می توان از آن برای اتصال گره شما به دیگری از طریق شناسه استفاده کرد و این گره را در کودکی علامت گذاری کرد. از آنجا که هر کتاب موجودیت خاص خود است و به گره های دیگر متصل نیست ، این را به عنوان خالی گذاشته اید ، به این معنی که والد ندارد.
  • کودکان به عنوان راهی برای پیوند گره ها شبیه به والدین هستند ، اما آرایه ای از شناسه ها را می گیرد. از آنجا که هر کتاب فرزندی ندارد ، آرایه را خالی گذاشته اید.
  • داخلی شیئی است که زمینه های بسیار ویژه سیستم مدیریت گره داخلی Gatsby و سایر افزونه ها را با هم گروه بندی می کند. این فقط می تواند شامل فیلدهای رسمی باشد ، به همین دلیل است که شما شیء کتاب را در آن پخش نکرده اید.
  • type یک رشته منحصر به فرد در سطح جهان است که نوع گره ای را که ایجاد می کنید توصیف می کند و بعداً هنگام درخواست گره ها از طریق GraphQL مورد استفاده قرار می گیرد.
  • contentDigest یک رشته هش است که از محتویات گره و ابزار کمکی Gatsby createContentDigest ساخته شده است. این فیلد به Gatsby کمک می کند تا تشخیص دهد که یک گره چه زمانی تغییر کرده است ، زیرا در صورت اصلاح هرگونه ویژگی شیء کتاب ، رشته هش تغییر می کند.

شما به تازگی کدی را اضافه کرده اید که محتوای منبع شما را می گیرد و با آن گره های جدید Gatsby ایجاد می کند و آنها را در محیط Gatsby به اشتراک می گذارد. در مرحله بعد ، شما تأیید می کنید که این گره ها در لایه داده GraphQL ظاهر می شوند و می توان آنها را پرس و جو کرد.

مرحله 5 – (اختیاری) بازرسی خروجی گره با API GraphQL

در حال حاضر ، شما محتوای منبع خود را به داخل Gatsby کشانده اید و از آن برای ایجاد گره های جدید استفاده کرده اید. به عنوان جایگزینی برای اشکال زدایی دستی با نقاط شکست یا دستورات ورود به سیستم ، در این مرحله از GraphQL IDE تعاملی برای تأیید اینکه این گره های جدید در حال ایجاد شدن هستند و می توانند با API GraphQL پرس و جو شوند ، استفاده خواهید کرد.

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

npm run develop

علاوه بر راه اندازی نسخه زنده سایت Gatsby ، فرمان develop همچنین سرور GraphQL و IDE محلی را نیز نشان می دهد. برای تأیید اینکه کد شما در gatsby-node.js تمام گره های کتاب را ایجاد می کند ، از این پرس و جو GraphQL برای دریافت عناوین کتاب ، شناسه های صفحه و شناسه های Gatsby استفاده خواهید کرد:

{
  allBookWikiPage {
    edges {
      node {
        title
        pageid
        id
      }
    }
  }
}

برای اجرای این پرس و جو ، یا GraphQL IDE تعاملی را در localhost باز کنید: 8000/___ graphql و قبل از اجرا پرس و جو را در سمت چپ قرار دهید یا از طریق cURL آن را پرس و جو کنید.

curl –location –request POST ‘http://localhost:8000/___graphql’ \
–header ‘Content-Type: application/json’ \
–data-raw ‘{
“query”: “{ allBookWikiPage { edges { node { title pageid id } } } }”
}’

پاسخ JSON چیزی شبیه به این خواهد بود:

{
  "data": {
    "allBookWikiPage": {
      "edges": [
        {
          "node": {
            "title": "The C Programming Language",
            "pageid": 379671,
            "id": "818771ca-40aa-5cfd-b9e7-fddff093d5ec"
          }
        },
        ...
      ]
    }
  },
  "extensions": {}
}

پس از تأیید اینکه گره های منبع سفارشی جدید شما ایجاد شده اند و در لایه داده GraphQL قابل دسترسی هستند ، مرحله بعدی استفاده از آنها برای ایجاد محتوای قابل مشاهده برای بازدیدکنندگان سایت یا برنامه شما است.

مرحله 6 – (اختیاری) ایجاد صفحات بر اساس گره ها

تا کنون ، تمام مراحل قبلی بر ایجاد گره های داخلی Gatsby متمرکز شده است ، از جمله آخرین مرحله تأیید ایجاد و توانایی بازیابی آنها. با این حال ، این گره ها فقط برای کد در حال اجرا در پروژه Gatsby شما قابل مشاهده هستند ، نه برای بازدیدکنندگان از سایت یا برنامه شما. در این مرحله ، شما یک فایل قالب صفحه React اضافه کرده و آن را به گره های خود وصل می کنید تا محتوای افزونه منبع شما به صفحات وب واقعی واقعی تبدیل شود.

روش های مختلفی برای ایجاد صفحات بر اساس گره های Gatsby وجود دارد ، اما برای این آموزش شما از API File System Route استفاده خواهید کرد ، که صفحات را بر اساس نحو نام فایل خاص ایجاد می کند.

ابتدا یک فایل خالی در src/pages با نام فایل {BookWikiPage.title} .js ایجاد کنید. مهاربندهای پیچ دار به Gatsby می گویند که نام فایل از API مسیر سیستم استفاده می کند و در داخل براکت ها ، BookWikiPage.title به Gatsby می گوید که برای هر عنوان کتاب منحصر به فرد صفحه ای ایجاد کند. توجه داشته باشید که دیگر روی فایلهای موجود در فهرست افزونه ها کار نمی کنید ، اما اکنون در داخل پروژه اصلی Gatsby کار می کنید.

در مرحله بعد ، کدی را به آن فایل اضافه کنید که گره کتاب را گرفته و آن را به عنوان یک صفحه وب نمایش می دهد:

import { graphql } from "gatsby";
import * as React from "react";
import Layout from "../components/layout";
import Seo from "../components/seo";

export default function BookPageTemplate({ data: { bookWikiPage } }) {
  const { title, extract, fullurl } = bookWikiPage;
  return (
    <Layout>
      <Seo title={title} />
      <h1>{title}</h1>
      <blockquote>{extract}</blockquote>

      <i>This article uses material from the Wikipedia article <a href={fullurl} target="_blank" rel="noreferrer">"{title}"</a>, which is released under the <a href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share-Alike License 3.0</a>.</i>
    </Layout>
  );
}

export const pageQuery = graphql`
  query ($id: String!) {
    bookWikiPage(id: { eq: $id }) {
      title
      extract
      fullurl
    }
  }
`;

در انتهای کد شما یک متغیر صادر شده به نام pageQuery وجود دارد که از تگ Gatsby GraphQL استفاده می کند. Gatsby پرس و جو GraphQL را که از آن استفاده می کند ، ارزیابی کرده و نتایج را به تابع BookPageTemplate منتقل می کند.

تابع BookPageTemplate ، که جزء React است ، سپس نتایج پرس و جو GraphQL را گرفته و با جاسازی مقادیر در JSX که برمی گرداند ، آنها را به عنوان بخشی از یک صفحه وب نمایش می دهد. عنوان کتاب به عنوان عنوان اصلی و عنوان صفحه استفاده می شود ، عصاره به عنوان نقل قول بلوک نمایش داده می شود و پیوندی به صفحه ورود کامل ویکی پدیا در پایین تعبیه شده است.

شما همچنین با استفاده از پیش فرض صادرات قبل از اعلان ، عملکرد BookPageTemplate را به عنوان صادرات پیش فرض علامت گذاری می کنید ، زیرا Gatsby انتظار دارد که جزء React مسئول تولید صفحه رندر شده نهایی را به عنوان صادرات پیش فرض هر فایل قالب صفحه بیابد.

پس از افزودن کد قالب React به فایل ، تغییرات را ذخیره کرده و ببندید. به http: // localhost: 8000/the-c-programming-language بروید تا یک صفحه نمونه را ارائه دهید:

برای نمایش فهرستی از این گره های جدید و صفحات مرتبط با آنها ، همچنین یک صفحه فهرست اختصاصی ایجاد می کنید که همه کتابها را در یک مکان نمایش می دهد. در قسمت src/pages یک فایل جدید با نام فایل books.js ایجاد کنید. بعد ، کد زیر را به آن اضافه کنید:

src/pages/books.js

import { graphql, Link } from "gatsby";
import * as React from "react";
import Layout from "../components/layout";
import Seo from "../components/seo";

export default function BookListingsPageTemplate({ data: { allBookWikiPage } }) {
  return (
    <Layout>
      <Seo title="Programming Books Listing" />
      <p>Here are some computer programming books that have their own Wikipedia entries:</p>

      {allBookWikiPage.edges.map((edge) => {
        const node = edge.node;
        return (
          <details key={node.title}>
            <summary>{node.title}</summary>

            <div className="details-body">
              <p>{node.extract}</p>
              <div className="links">
                <Link href={node.gatsbyPath}>Internal Page</Link>
                <a rel="noreferrer" href={node.fullurl}>Wikipedia Page</a>
              </div>
            </div>
          </details>
        )
      })}
    </Layout>
  );
}

export const pageQuery = graphql`
  query {
    allBookWikiPage {
      edges {
        node {
          title
          extract
          gatsbyPath(filePath: "/{BookWikiPage.title}")
          fullurl
        }
      }
    }
  }
`;

شبیه به الگوی صفحه {BookWikiPage.title} .js ، این فایل همچنین از برچسب GraphQL pageQuery برای برداشتن داده ها از لایه GraphQL و ارسال آن به یک جزء React استفاده می کند. با این حال ، در حالی که الگوی قبلی یک کتاب را بر اساس شناسه ارائه می داد ، این الگو فهرستی از همه کتابها را ارائه می دهد ، در حالی که به صفحات کتاب جداگانه پیوند داده شده است.

هر فهرست کتاب از یک عنصر <details> استفاده می کند ، که این لیست را قادر می سازد تا قسمت کامل کتاب و پیوندها را نشان دهد یا برای نشان دادن عنوان فقط جمع شود. با پیروی از بهترین روش ها ، شما همچنین یک مقدار منحصر به فرد را به کلید در حین تکرار در آرایه منتقل می کنید ، با استفاده از مولفه Gatsby Link برای پیوندهای داخلی و یک برچسب برای پیوندهای خارجی.

رشته gatsbyPath (filePath: “/{BookWikiPage.title}”) در پرس و جو GraphQL از تابع () gatsbyPath ویژه برای بازیابی مسیر عمومی ایجاد شده بر اساس نام فایل API مسیر فایل سیستم استفاده می کند.

این فایل را ذخیره کرده و از آن خارج شوید.

با وجود تمام کتابهای موجود در یک صفحه ، حتی با بخشهای جمع شونده همه چیز کمی شلوغ شده است ، بنابراین آخرین مرحله این است که برخی از ظاهر را اضافه کنید تا خوانندگان بتوانند فهرست را آسانتر کنند. یک فایل شیوه نامه جدید در src/styles/books.css ایجاد کنید. می توانید این کار را در مرورگر فایل خود یا با خط فرمان از ریشه پروژه Gatsby انجام دهید:

mkdir -p ./src/styles
touch ./src/styles/books.css

سپس CSS زیر را به فایل اضافه کنید:

src/styles/books.css

details {
  border: 1px dotted black;
  margin: 6px;
  padding: 6px;
}

.details-body {
  background-color: #eedeff;
  margin: 4px 0px 2px 12px;
  padding: 4px;
  border-radius: 4px;
}

.links {
  display: flex;
  justify-content: space-evenly;
}

این CSS در اطراف هر فهرست کتاب ، فاصله و حاشیه های موجود در فهرست و فاصله بین پیوندهای داخلی و خارجی کتاب را اضافه می کند. پس از افزودن CSS به فایل ، قبل از ادامه آن را ذخیره و ببندید.

در نهایت ، الگوی صفحه فهرست کتاب را به روز کنید تا این فایل CSS را در آن بکشید:

src/pages/books.js

import { graphql, Link } from "gatsby";
import * as React from "react";
import Layout from "../components/layout";
import Seo from "../components/seo";
import "../styles/books.css";

این فایل را با خط وارد کردن CSS که به تازگی اضافه شده است ذخیره و ببندید.

برای مشاهده نتایج ، دوباره فرمان develop را اجرا کنید تا سرور توسعه ظاهر شود و صفحات جدید را پیش نمایش کنید:

npm run develop

اکنون می توانید به صفحه فهرست کتابهای خود در localhost دسترسی داشته باشید: 8000/books/.

شما اکنون نه تنها یک افزونه منبع Gatsby را از ابتدا ایجاد کرده اید ، بلکه از آن برای تولید صفحات بر اساس یک قالب React نیز استفاده کرده اید.

نتیجه

با دنبال کردن مراحل این آموزش ، شما اکنون ساخت افزونه منبع سفارشی را که محتوای خارجی را در پروژه Gatsby شما وارد می کند ، به پایان رسانده و از آن برای تأمین صفحات جدید در سایت خود استفاده کرده اید.

منبع افزونه ها عمق زیادی دارد. اگر علاقه مند به پیروی از بهترین شیوه ها و یادگیری مفاهیم افزونه منبع پیشرفته تر هستید ، در اینجا مواردی وجود دارد که ممکن است برای شما جالب باشد:

  • اگر می خواهید افزونه خود را با جهان به اشتراک بگذارید ، می توانید این کار را با انتشار آن در npm انجام دهید. می توانید این راهنمای انتشار بسته های npm را دنبال کنید و برای ارسال به کتابخانه افزونه Gatsby ، آن را با این گردش کار دنبال کنید.
  • برای افزونه های منبع که کارهای زیادی را با ورودی هایی انجام می دهند که برای مدت زمان یکسانی باقی می مانند ، می توانید از مزایای مکانیزم کش Gatsby بین ساخت ها استفاده کنید.
  • اگر گره های شما به یکدیگر مرتبط هستند یا به گره هایی که توسط افزونه های دیگر ایجاد شده اند ، می توانید آنها را از طریق روابط به هم پیوند دهید. این به طور خلاصه در این آموزش توضیح داده شده است ، اما می توانید جزئیات بیشتری را در اسناد Gatsby بیابید.
  • افزونه ترانسفورماتور افزونه ای است که فقط گره های یک نوع را گرفته و آنها را به گره های جدید یا اصلاح شده تبدیل می کند. در اسناد افزونه ترانسفورماتور Gatsby می توانید اطلاعات بیشتری در مورد آنها بخوانید.

c

 

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه استفاده از دکوراتورها در TypeScript

ورود به سایت

معرفی

TypeScript افزونه ای از زبان جاوا اسکریپت است که از زمان اجرای جاوا اسکریپت با یک نوع تایپ کننده زمان کامپایل استفاده می کند. این ترکیب به توسعه دهندگان اجازه می دهد تا از اکوسیستم جاوا اسکریپت و ویژگی های زبان کامل استفاده کنند ، در حالی که علاوه بر این ، نوع تایپ استاتیک ، شمارش ها ، کلاس ها و رابط ها را در بالای آن اضافه می کنند. یکی از این ویژگی های اضافی پشتیبانی از دکوراتور است.

دکوراتورها راهی برای decorator اعضای یک کلاس یا خود کلاس با قابلیت های اضافی هستند. هنگامی که از یک decorator کننده برای یک کلاس یا عضو کلاس استفاده می کنید ، در واقع یک تابع را فراخوانی می کنید که جزئیات decorator شده را دریافت می کند ، و اجرای decorator قادر خواهد بود کد را به صورت پویا تغییر داده و قابلیت های اضافی را اضافه کند. کاهش کد بویلر آنها راهی برای متا برنامه نویسی در TypeScript هستند ، که یک تکنیک برنامه نویسی است که برنامه نویس را قادر می سازد تا کدی ایجاد کند که از کدهای دیگر خود برنامه به عنوان داده استفاده کند.

این آموزش به شما نشان می دهد که چگونه decorator خود را در TypeScript برای کلاس ها و اعضای کلاس ایجاد کنید ، و همچنین نحوه استفاده از آنها. شما را از طریق نمونه کد های مختلف راهنمایی می کند ، که می توانید آنها را در محیط TypeScript خود یا TypeScript Playground دنبال کنید ، یک محیط آنلاین که به شما امکان می دهد TypeScript را مستقیماً در مرورگر بنویسید.

پیش نیازها

برای پیگیری این آموزش ، شما نیاز دارید:

  • محیطی که در آن می توانید برنامه های TypeScript را اجرا کنید تا همراه با مثال ها دنبال کنید. برای تنظیم این دستگاه در دستگاه محلی خود ، به موارد زیر نیاز دارید.
    • هر دو Node و npm (یا نخ) به منظور اجرای یک محیط توسعه که بسته های مربوط به TypeScript را مدیریت می کند ، نصب شده است. این آموزش با Node.js نسخه 14.3.0 و npm نسخه 6.14.5 آزمایش شده است. برای نصب روی macOS یا اوبونتو 18.04 ، مراحل نحوه نصب Node.js و ایجاد محیط توسعه محلی در macOS یا بخش Installing using a PPA از نحوه نصب Node.js در اوبونتو 18.04 را دنبال کنید. اگر از زیر سیستم Windows برای Linux (WSL) استفاده می کنید ، این نیز کار می کند.
    • علاوه بر این ، به TypeScript Compiler (tsc) نصب شده بر روی دستگاه خود نیاز دارید. برای انجام این کار ، به وب سایت رسمی TypeScript مراجعه کنید.
  • اگر نمی خواهید محیط TypeScript را در دستگاه محلی خود ایجاد کنید ، می توانید از زمین بازی رسمی TypeScript برای پیگیری استفاده کنید.
  • شما به دانش کافی در مورد جاوا اسکریپت ، به ویژه نحو ES6+ ، مانند تخریب ، عملگرهای استراحت و واردات/صادرات نیاز دارید. اگر به اطلاعات بیشتری در مورد این موضوعات نیاز دارید ، خواندن نحوه کدگذاری در سری JavaScript توصیه می شود
  • این آموزش به جنبه های ویرایشگرهای متنی که از TypeScript پشتیبانی می کنند اشاره می کند و خطاهای خطی را نشان می دهد. این برای استفاده از TypeScript ضروری نیست ، اما از ویژگیهای TypeScript بیشتر استفاده می کند. برای به دست آوردن مزایای این موارد ، می توانید از ویرایشگر متنی مانند Visual Studio Code استفاده کنید که از TypeScript پشتیبانی کامل دارد. همچنین می توانید این مزایا را در TypeScript Playground امتحان کنید

همه نمونه های نشان داده شده در این آموزش با استفاده از TypeScript نسخه 4.2.2 ایجاد شده است.

فعال کردن پشتیبانی Decorators در TypeScript

در حال حاضر ، decorator هنوز یک ویژگی آزمایشی در TypeScript هستند و بنابراین ، ابتدا باید آن را فعال کنید. در این بخش ، بسته به نحوه کار با TypeScript ، نحوه فعال کردن decorator در TypeScript را خواهید دید.

CLI کامپایلر TypeScript

برای فعال کردن پشتیبانی دکوراتورها در هنگام استفاده از TypeScript Compiler CLI (tsc) تنها مرحله اضافی مورد نیاز این است که یک پرچم اضافی –experimentalDecorators:

tsc –experimentalDecorators

tsconfig.json

هنگام کار در پروژه ای که دارای فایل tsconfig.json است ، برای فعال کردن decorator تجربی ، باید ویژگی experimentalDecorators را به شیء compilerOptions اضافه کنید:

{
“compilerOptions”: {
“experimentalDecorators”: true
}
}

در زمین بازی TypeScript ، دکوراتورها به طور پیش فرض فعال هستند.

با استفاده از نحو دکوراتور

در این بخش ، شما در کلاسهای TypeScript از decorator استفاده خواهید کرد.

در TypeScript ، می توانید با استفاده از نحو خاصexpression ، decorator کننده ایجاد کنید ، جایی که بیان یک تابع است که به طور خودکار در زمان اجرا با جزئیات مربوط به هدفdecorator فراخوانی می شود.

هدف یک دکوراتور بستگی به جایی دارد که آنها را اضافه می کنید. در حال حاضر ، decorator را می توان به اجزای زیر کلاس اضافه کرد:

  • خود اعلام کلاس
  • خواص
  • دستیاران
  • مواد و روش ها
  • مولفه های

برای مثال ، فرض کنید شما یک decorator به نام مهر و موم شده دارید که Object.seal را در یک کلاس فراخوانی می کند. برای استفاده از دکوراتور خود می توانید موارد زیر را بنویسید:

@sealed
class Person {}

در کد برجسته شده توجه کنید که decorator را درست قبل از هدف decorator مهر و موم شده خود اضافه کرده اید ، در این مورد ، اعلان کلاس Person.

همین امر برای انواع دیگر decorators معتبر است:

@classDecorator
class Person {
  @propertyDecorator
  public name: string;

  @accessorDecorator
  get fullName() {
    // ...
  }

  @methodDecorator
  printName(@parameterDecorator prefix: string) {
    // ...
  }
}

 

برای افزودن چند decorator ، آنها را یکی پس از دیگری به هم اضافه کنید:

@decoratorA
@decoratorB
class Person {}

ایجاد دکوراتورهای کلاس در TypeScript

در این بخش مراحل ایجاد decorator کلاس در TypeScript را طی خواهید کرد.

برای decorator به نامdecoratorA ، به TypeScript می گویید که باید تابع decoratorA را فراخوانی کند. یک تابع با جزئیات نحوه استفاده از decorator در کد خود فراخوانی می شود. به عنوان مثال ، اگر decorator را برای اعلان کلاس اعمال کرده اید ، تابع جزئیات مربوط به کلاس را دریافت می کند. این عملکرد باید در حدی باشد که دکوراتور شما بتواند کار کند.

برای ایجاد دکوراتور خود ، باید تابعی با همان نام decorator خود ایجاد کنید. به این معنی که برای ایجاد decorator کلاس مهر و موم شده که در قسمت قبل مشاهده کردید ، باید یک تابع مهر و موم شده ایجاد کنید که مجموعه خاصی از پارامترها را دریافت می کند. بیایید دقیقاً همین کار را انجام دهیم:

@sealed
class Person {}

function sealed(target: Function) {
  Object.seal(target);
  Object.seal(target.prototype);
}

پارامتر (های) منتقل شده به دکوراتور بستگی به محل استفاده از دکوراتور دارد. پارامتر اول معمولاً هدف نامیده می شود.

دکوراتور مهر و موم شده فقط در اعلان های کلاس استفاده می شود ، بنابراین عملکرد شما یک پارامتر واحد ، هدف ، که از نوع Function است دریافت می کند. این سازنده کلاسی خواهد بود که decorator کننده روی آن اعمال شده است.

در تابع مهر و موم شده ، سپس Object.seal را روی هدف ، که سازنده کلاس است ، و همچنین در نمونه اولیه آنها فراخوانی می کنید. هنگامی که این کار را انجام می دهید ، هیچ ویژگی جدیدی نمی تواند به سازنده کلاس یا ویژگی آنها اضافه شود ، و خصوصیات موجود به عنوان غیر قابل تنظیم علامت گذاری می شوند.

مهم است که به یاد داشته باشید که در حال حاضر نمی توان نوع TypeScript هدف را هنگام استفاده از decorator گسترش داد. این بدان معناست که ، به عنوان مثال ، شما نمی توانید یک فیلد جدید با استفاده از یک تزئین کننده به کلاس اضافه کنید و آن را از نظر نوع ایمن کنید.

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

شما اولین decorator کننده خود را ایجاد کرده اید و از آن در کلاس استفاده کرده اید. در قسمت بعدی نحوه ایجاد کارخانه های decorator را خواهید آموخت.

ایجاد Decorator Factories

گاهی اوقات هنگام استفاده از دکوراتور باید گزینه های اضافی را به دکوراتور منتقل کنید و برای این کار باید از کارخانه های decorator استفاده کنید. در این بخش نحوه ایجاد آن کارخانه ها و استفاده از آنها را خواهید آموخت.

کارخانه های decorator توابعی هستند که عملکرد دیگری را برمی گردانند. آنها این نام را دریافت می کنند زیرا خود اجرای decorator نیستند. در عوض ، آنها عملکرد دیگری را که مسئول اجرای decorator است ، باز می گردانند و به عنوان یک تابع بسته بندی عمل می کنند. آنها در سفارشی سازی دکوراتورها مفید هستند ، زیرا اجازه می دهند کد مشتری هنگام استفاده از گزینه ها به decorator منتقل کند.

بیایید تصور کنیم که شما یک دکوراتور کلاس به نام decoratorA دارید و می خواهید گزینه ای را اضافه کنید که می توانید هنگام فراخوانی با دکوراتور مانند پرچم بولی تنظیم کنید. شما می توانید با نوشتن یک کارخانه تزئیناتی مشابه کارخانه زیر به این مهم برسید:

const decoratorA = (someBooleanFlag: boolean) => {
  return (target: Function) => {
  }
}

در اینجا ، تابع decoratorA با پیاده سازی تزئین کننده ، عملکرد دیگری را برمی گرداند. توجه کنید که چگونه کارخانه تزئینات پرچم بولی را به عنوان تنها پارامتر خود دریافت می کند:

const decoratorA = (someBooleanFlag: boolean) => {
  return (target: Function) => {
  }
}

هنگام استفاده از دکوراتور ، می توانید مقدار این پارامتر را منتقل کنید. کد برجسته شده را در مثال زیر مشاهده کنید:

const decoratorA = (someBooleanFlag: boolean) => {
  return (target: Function) => {
  }
}

@decoratorA(true)
class Person {}

در اینجا ، وقتی از decoratorA decorator استفاده می کنید ، قرار است کارخانه تزئینات با پارامتر someBooleanFlag روی true تنظیم شود. سپس اجرای تزئین کننده خود اجرا می شود. این به شما امکان می دهد رفتار دکوراتور خود را بر اساس نحوه استفاده از آن تغییر دهید ، و سفارشی سازی و استفاده مجدد از دکوراتورها را از طریق برنامه خود آسان کنید.

توجه داشته باشید که لازم است تمام پارامترهای مورد انتظار کارخانه دکوراتور را گذرانده باشید. اگر به سادگی از دکوراتور بدون عبور از پارامترها استفاده کرده اید ، مانند مثال زیر:

const decoratorA = (someBooleanFlag: boolean) => {
  return (target: Function) => {
  }
}

@decoratorA
class Person {}

کامپایلر TypeScript دو خطا به شما می دهد که ممکن است بسته به نوع تزئین کننده متفاوت باشد. برای تزئین کنندگان کلاس خطاها 1238 و 1240 است:

 

Output

Unable to resolve signature of class decorator when called as an expression.
  Type '(target: Function) => void' is not assignable to type 'typeof Person'.
    Type '(target: Function) => void' provides no match for the signature 'new (): Person'. (1238)
Argument of type 'typeof Person' is not assignable to parameter of type 'boolean'. (2345)

شما فقط یک کارخانه تزئینات ایجاد کرده اید که قادر به دریافت پارامترها و تغییر رفتار آنها بر اساس این پارامترها است. در مرحله بعد با نحوه ایجاد تزئین کننده املاک آشنا می شوید.

ایجاد Property Decorators

ویژگی های کلاس مکان دیگری است که می توانید از دکوراتور استفاده کنید. در این بخش نحوه ایجاد آنها را بررسی می کنید.

هر دکوراتور املاک پارامترهای زیر را دریافت می کند:

  • برای خواص استاتیک ، تابع سازنده کلاس. برای سایر ویژگی ها ، نمونه اولیه کلاس.
  • نام عضو.

در حال حاضر ، هیچ راهی برای به دست آوردن توصیف ویژگی به عنوان پارامتر وجود ندارد. این به دلیل روشی است که طراحان ویژگی در TypeScript راه اندازی می شوند.

در اینجا یک عملکرد تزئین کننده وجود دارد که نام اعضا را روی کنسول چاپ می کند:

const printMemberName = (target: any, memberName: string) => {
console.log(memberName);
};

class Person {
@printMemberName
name: string = “Jon”;
}

وقتی کد TypeScript بالا را اجرا می کنید ، موارد زیر را در کنسول چاپ می کنید:

 

Output

name

می توانید از طراحان املاک برای نادیده گرفتن ملک مورد تزئین استفاده کنید. این را می توان با استفاده از Object.defineProperty همراه با یک setter و getter جدید برای ویژگی انجام داد. بیایید ببینیم چگونه می توانید یک تزئین کننده با نام فهرست مجاز ایجاد کنید ، که فقط اجازه می دهد یک ویژگی بر روی مقادیر موجود در یک لیست مجاز استاتیک تنظیم شود:

const allowlist = ["Jon", "Jane"];

const allowlistOnly = (target: any, memberName: string) => {
  let currentValue: any = target[memberName];

  Object.defineProperty(target, memberName, {
    set: (newValue: any) => {
      if (!allowlist.includes(newValue)) {
        return;
      }
      currentValue = newValue;
    },
    get: () => currentValue
  });
};

ابتدا ، شما یک لیست مجاز استاتیک در بالای کد ایجاد می کنید:

const allowlist = [“Jon”, “Jane”];

سپس در حال پیاده سازی تزئین کننده اموال هستید:

const allowlistOnly = (target: any, memberName: string) => {
  let currentValue: any = target[memberName];

  Object.defineProperty(target, memberName, {
    set: (newValue: any) => {
      if (!allowlist.includes(newValue)) {
        return;
      }
      currentValue = newValue;
    },
    get: () => currentValue
  });
};

توجه داشته باشید که چگونه از هر کدام به عنوان نوع هدف استفاده می کنید:

const allowlistOnly = (target: any, memberName: string) => {

برای طراحان ویژگی ، نوع پارامتر هدف می تواند سازنده کلاس یا نمونه اولیه کلاس باشد ، در این شرایط استفاده از آن آسان تر است.

در خط اول پیاده سازی تزئین کننده خود ، مقدار فعلی دارایی را که تزئین می کنید در متغیر currentValue ذخیره می کنید:

let currentValue: any = target[memberName];

برای خواص استاتیک ، در صورت وجود ، مقدار پیش فرض آنها تنظیم می شود. برای خواص غیر استاتیک ، این همیشه تعریف نشده است. این به این دلیل است که در زمان اجرا ، در کد جاوا اسکریپت کامپایل شده ، تزئین کننده قبل از اینکه ویژگی نمونه روی مقدار پیش فرض تنظیم شود ، اجرا می شود.

سپس با استفاده از Object.defineProperty ویژگی را لغو می کنید:

Object.defineProperty(target, memberName, {
  set: (newValue: any) => {
    if (!allowlist.includes(newValue)) {
      return;
    }
    currentValue = newValue;
  },
  get: () => currentValue
});

فراخوانی Object.defineProperty دارای getter و setter است. دریافت کننده مقدار ذخیره شده در متغیر currentValue را برمی گرداند. اگر تنظیم کننده مقدار currentVariable را روی newValue تنظیم کند ، اگر در لیست مجاز باشد.

بیایید از دکوراتوری که شما نوشتید استفاده کنیم. کلاس Person زیر را ایجاد کنید:

class Person {
  @allowlistOnly
  name: string = "Jon";
}

اکنون یک نمونه جدید از کلاس خود ایجاد می کنید ، و تنظیمات آزمایشی و بدست آوردن ویژگی نمونه نام:

const allowlist = ["Jon", "Jane"];

const allowlistOnly = (target: any, memberName: string) => {
  let currentValue: any = target[memberName];

  Object.defineProperty(target, memberName, {
    set: (newValue: any) => {
      if (!allowlist.includes(newValue)) {
        return;
      }
      currentValue = newValue;
    },
    get: () => currentValue
  });
};

class Person {
  @allowlistOnly
  name: string = "Jon";
}

const person = new Person();
console.log(person.name);

person.name = "Peter";
console.log(person.name);

person.name = "Jane";
console.log(person.name);

 

هنگام اجرای کد باید خروجی زیر را مشاهده کنید:

 

Output

Jon
Jon
Jane

مقدار هرگز روی Peter تنظیم نمی شود ، زیرا Peter در لیست مجاز نیست.

اگر می خواهید کد خود را کمی بیشتر استفاده کنید و اجازه دهید هنگام استفاده از دکوراتور ، لیست مجاز تنظیم شود ، چه می کنید؟ این یک مورد استفاده عالی برای decorator factories. است. بیایید دقیقاً همین کار را انجام دهیم ، با تبدیل دکوراسیون مجاز خود فقط دکوراتور به decorator factories.:

const allowlistOnly = (allowlist: string[]) => {
  return (target: any, memberName: string) => {
    let currentValue: any = target[memberName];

    Object.defineProperty(target, memberName, {
      set: (newValue: any) => {
        if (!allowlist.includes(newValue)) {
          return;
        }
        currentValue = newValue;
      },
      get: () => currentValue
    });
  };
}

در اینجا شما پیاده سازی قبلی خود را به یک عملکرد دیگر ، یک کارخانه تزئینات ، پیچانده اید. کارخانه تزئینات یک پارامتر به نام مجاز لیست دریافت می کند که مجموعه ای از رشته ها است.

اکنون برای استفاده از دکوراتور خود ، باید از فهرست مجاز مانند کد برجسته زیر عبور کنید:

class Person {
  @allowlistOnly(["Claire", "Oliver"])
  name: string = "Claire";
}

سعی کنید کدی شبیه کد قبلی که نوشتید اجرا کنید ، اما با تغییرات جدید:

const allowlistOnly = (allowlist: string[]) => {
  return (target: any, memberName: string) => {
    let currentValue: any = target[memberName];

    Object.defineProperty(target, memberName, {
      set: (newValue: any) => {
        if (!allowlist.includes(newValue)) {
          return;
        }
        currentValue = newValue;
      },
      get: () => currentValue
    });
  };
}

class Person {
  @allowlistOnly(["Claire", "Oliver"])
  name: string = "Claire";
}

const person = new Person();
console.log(person.name);
person.name = "Peter";
console.log(person.name);
person.name = "Oliver";
console.log(person.name);

کد باید خروجی زیر را به شما بدهد:

 

Output

Claire
Claire
Oliver

نشان می دهد که آنطور که انتظار می رود کار می کند ، person.name هرگز روی Peter تنظیم نمی شود ، زیرا Peter در فهرست مجاز داده شده نیست.

اکنون که اولین تزئین کننده دارایی خود را با استفاده از عملکرد معمول تزئین کننده و کارخانه تزئینات ایجاد کرده اید ، وقت آن است که به نحوه ایجاد تزئینات برای دستیاران کلاس نگاهی بیندازید.

ایجاد Accessor Decorators

در این قسمت نگاهی به چگونگی تزئین اعضای کلاس می اندازید.

درست مانند دکوراتورهای املاک ، دکوراتورهای مورد استفاده در یک accessor پارامترهای زیر را دریافت می کنند:

برای خواص استاتیک ، تابع سازنده کلاس ، برای همه خواص دیگر ، نمونه اولیه کلاس.
نام عضو.
اما متفاوت از دکوراتور ویژگی ، پارامتر سوم را نیز با ویژگی توصیف کننده ویژگی عضو دسترسی دریافت می کند.

با توجه به این واقعیت که ویژگی های توصیف کننده شامل هر دو تنظیم کننده و گیرنده برای یک عضو خاص است ، تزئین کننده های جانبی فقط می توانند برای تنظیم کننده یا گیرنده یک عضو واحد اعمال شوند ، نه برای هر دو.

اگر یک مقدار از تزئین کننده accessor خود را برگردانید ، این مقدار به عنوان توصیف کننده ویژگی جدید accessor برای هر دو گروه getter و setter تبدیل می شود.

در اینجا نمونه ای از یک تزئین کننده است که می تواند برای تغییر پرچم قابل شمارش دسترسی گیرنده/تنظیم کننده استفاده شود:

const enumerable = (value: boolean) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    propertyDescriptor.enumerable = value;
  }
}

در مثال به نحوه استفاده از کارخانه تزئینات توجه کنید. این به شما این امکان را می دهد که هنگام تماس با دکوراتور پرچم شمارش شده را مشخص کنید. در اینجا نحوه استفاده از دکوراتور خود آورده شده است:

class Person {
  firstName: string = "Jon"
  lastName: string = "Doe"

  @enumerable(true)
  get fullName () {
    return `${this.firstName} ${this.lastName}`;
  }
}

دکوراتورهای اکسسوری شبیه به دکوراتورهای املاک هستند. تنها تفاوت این است که آنها پارامتر سوم را با توصیف کننده ویژگی دریافت می کنند. اکنون که اولین تزئین کننده اکسسوری خود را ایجاد کرده اید ، بخش بعدی نحوه ایجاد تزئین کننده متد را به شما نشان می دهد.

ایجاد Method Decorators

در این قسمت نگاهی به نحوه استفاده از تزئین کننده های متد می اندازید.

اجرای روش های تزئینات بسیار شبیه به نحوه ایجاد تزئینات اکسسوری است. پارامترهای ارسال شده به اجرای تزئینی مشابه پارامترهایی است که به تزئین کننده های اکسسوری ارسال شده است.

بیایید از همان دکوراتور قابل شمارش که قبلاً ایجاد کرده اید دوباره استفاده کنیم ، اما این بار در متد getFullName کلاس Person زیر:

const enumerable = (value: boolean) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    propertyDescriptor.enumerable = value;
  }
}

class Person {
  firstName: string = "Jon"
  lastName: string = "Doe"

  @enumerable(true)
  getFullName () {
    return `${this.firstName} ${this.lastName}`;
  }
}

اگر مقداری را از تزئین کننده متد خود برگردانده اید ، این مقدار به توصیف کننده جدید ویژگی متد تبدیل می شود.

بیایید یک دکوراتور منسوخ ایجاد کنیم که وقتی از متد استفاده می شود پیام ارسال شده را روی کنسول چاپ می کند و پیامی را ثبت می کند که می گوید این روش منسوخ شده است:

const deprecated = (deprecationReason: string) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    return {
      get() {
        const wrapperFn = (...args: any[]) => {
          console.warn(`Method ${memberName} is deprecated with reason: ${deprecationReason}`);
          propertyDescriptor.value.apply(this, args)
        }

        Object.defineProperty(this, memberName, {
            value: wrapperFn,
            configurable: true,
            writable: true
        });
        return wrapperFn;
      }
    }
  }
}

 

در اینجا ، شما در حال ایجاد یک تزئین کننده با استفاده از یک کارخانه تزئینات هستید. این کارخانه تزئینی یک آرگومان واحد از نوع string دریافت می کند ، که دلیل عدم استفاده از آن است ، همانطور که در قسمت برجسته زیر نشان داده شده است:

const deprecated = (deprecationReason: string) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    // ...
  }
}

deprecationReason بعداً هنگام ورود پیام منسوخ شدن به کنسول استفاده می شود. در اجرای تزئین منسوخ شده خود ، یک مقدار را برمی گردانید. هنگامی که مقداری را از یک تزئین کننده متد برمی گردانید ، این مقدار روی توصیف کننده ویژگی این عضو بازنویسی می کند.

شما از این مزیت استفاده می کنید تا متد را به روش کلاس تزئین شده خود اضافه کنید. به این ترتیب می توانید پیاده سازی خود روش را تغییر دهید.

اما چرا فقط از Object.defineProperty به جای بازگشت یک تزئین کننده جدید برای روش استفاده نکنید؟ این امر ضروری است زیرا باید به مقدار این دسترسی داشته باشید ، که برای روشهای کلاس غیر استاتیک ، به نمونه کلاس متصل است. اگر مستقیماً از Object.defineProperty استفاده می کنید ، هیچ راهی برای بازیابی مقدار آن برای شما وجود نخواهد داشت ، و اگر متدی که به هر نحوی از این روش استفاده می کرد ، تزئین کننده هنگام اجرای روش پیچیده شده از داخل اجرای تزئین کننده ، کد شما را می شکند.

در مورد شما ، خود گیرنده این مقدار را برای نمونه های غیراستاتیک به نمونه کلاس و برای متدهای استاتیک به سازنده کلاس محدود می کند.

در داخل getter شما سپس یک تابع wrapper به صورت محلی ایجاد می کنید ، به نام wrapperFn ، این تابع با استفاده از console یک پیام را به کنسول وارد می کند. هشدار دهید ، با رد deprecationReason دریافت شده از کارخانه decorator ، سپس با استفاده از propertyDescriptor.value روش اصلی را فراخوانی می کنید. apply (this، args) ، به این ترتیب متد اصلی نامیده می شود که این مقدار به درستی به نمونه کلاس متصل شده است در صورتی که یک روش غیر استاتیک بود.

سپس از definProperty برای بازنویسی مقدار متد خود در کلاس استفاده می کنید. این مانند یک مکانیسم یادآوری عمل می کند ، زیرا تماس های متعدد با یک روش دیگر با گیرنده شما تماس نمی گیرد ، بلکه مستقیماً با wrapperFn تماس می گیرد. اکنون شما با استفاده از Object.defineProperty ، عضو کلاس را طوری تنظیم می کنید که wrapperFn شما به عنوان مقدار آن باشد.

بیایید از دکوراتور منسوخ شده شما استفاده کنیم:

const deprecated = (deprecationReason: string) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    return {
      get() {
        const wrapperFn = (...args: any[]) => {
          console.warn(`Method ${memberName} is deprecated with reason: ${deprecationReason}`);
          propertyDescriptor.value.apply(this, args)
        }

        Object.defineProperty(this, memberName, {
            value: wrapperFn,
            configurable: true,
            writable: true
        });
        return wrapperFn;
      }
    }
  }
}

class TestClass {
  static staticMember = true;

  instanceMember: string = "hello"

  @deprecated("Use another static method")
  static deprecatedMethodStatic() {
    console.log('inside deprecated static method - staticMember =', this.staticMember);
  }

  @deprecated("Use another instance method")
  deprecatedMethod () {
    console.log('inside deprecated instance method - instanceMember =', this.instanceMember);
  }
}

TestClass.deprecatedMethodStatic();

const instance = new TestClass();
instance.deprecatedMethod();

در اینجا ، شما یک TestClass با دو ویژگی ایجاد کرده اید: یکی استاتیک و دیگری غیر استاتیک. شما همچنین دو روش ایجاد کرده اید: یکی استاتیک و دیگری غیر استاتیک.

سپس از تزئین کننده منسوخ خود برای هر دو روش استفاده می کنید. هنگام اجرای کد ، موارد زیر در کنسول ظاهر می شود:

 

Output

(warning) Method deprecatedMethodStatic is deprecated with reason: Use another static method
inside deprecated static method - staticMember = true
(warning)) Method deprecatedMethod is deprecated with reason: Use another instance method
inside deprecated instance method - instanceMember = hello

این نشان می دهد که هر دو روش به درستی با عملکرد wrapper شما بسته شده است ، که پیامی را با دلیل منسوخ شدن به کنسول وارد می کند.

اکنون شما اولین تزئین کننده متد خود را با استفاده از TypeScript ایجاد کرده اید. بخش بعدی نحوه ایجاد آخرین نوع تزئین کننده پشتیبانی شده توسط TypeScript ، یک تزئین کننده پارامتر را به شما نشان می دهد.

ایجاد پارامترهای Decorators

تزئینات پارامتری را می توان در پارامترهای روش کلاس استفاده کرد. در این بخش نحوه ایجاد آن را خواهید آموخت.

عملکرد تزئین کننده مورد استفاده با پارامترها پارامترهای زیر را دریافت می کند:

برای خواص استاتیک ، تابع سازنده کلاس. برای سایر خصوصیات ، نمونه اولیه کلاس.
نام عضو.
فهرست پارامترها در لیست پارامترهای متد.
تغییر هر چیزی که مربوط به خود پارامتر باشد امکان پذیر نیست ، بنابراین چنین تزئیناتی فقط برای مشاهده استفاده از خود پارامترها مفید هستند (مگر اینکه از موارد پیشرفته تری مانند بازتاب داده های بازتاب استفاده کنید).

در اینجا یک نمونه از تزئین کننده است که شاخص پارامتر تزئین شده را به همراه نام روش چاپ می کند:

function print(target: Object, propertyKey: string, parameterIndex: number) {
  console.log(`Decorating param ${parameterIndex} from ${propertyKey}`);
}

سپس می توانید پارامتر decorators خود را مانند این استفاده کنید:

class TestClass {
  testMethod(param0: any, @print param1: any) {}
}

اجرای کد بالا باید موارد زیر را در کنسول نمایش دهد:

 

Output

Decorating param 1 from testMethod

شما اکنون یک  پارامتر decorator ایجاد کرده و اجرا کرده اید و نتیجه ای را که شاخص پارامتر decorator را برمی گرداند چاپ می کنید.

نتیجه
در این آموزش ، شما تمام decorators پشتیبانی شده توسط TypeScript را پیاده سازی کرده اید ، از آنها در کلاس ها استفاده کرده اید و تفاوت های هر یک را یاد گرفته اید. اکنون می توانید برای کاهش کد صفحه بویلر در پایگاه کد خود ، نوشتن دکوراتورهای خود را شروع کنید ، یا با اطمینان بیشتر از دکوراتورهای کتابخانه هایی مانند Mobx استفاده کنید.

decoratorMethod DecoratorsProperty DecoratorsTypeScriptپارامترهای Decoratorsجاواجاوا اسکریپتسرورسرور مجازیکامپایلر TypeScript

  • behnam gol mohamadi
  • ۰
  • ۰

مشارکت در نرم افزار منبع باز: Kubernetes

ورود به سایت

آیا علاقه دارید با جامعه Kubernetes درگیر شوید ، اما مطمئن نیستید از کجا شروع کنید؟ این پست وبلاگ با هدف کمک به رفع ابهام مربوط به مشارکت در یک پروژه منبع باز به بزرگی Kubernetes و ارائه تجربیات حدیثی به شما این ایده را می دهد که مشارکت در یک پروژه منبع باز مانند Kubernetes می تواند به عنوان یک مبتدی به نظر برسد.

امیدوارم با بیان جزئیات تجربه خود به عنوان مشارکت کننده ، به شما انگیزه دهم تا اولین قدم را برای شروع راه خود به عنوان مشارکت کننده منبع باز بردارید. شما می توانید بدون توجه به سابقه یا سالها تجربه خود در Kubernetes مشارکت داشته باشید. مشارکت همه بخش مهمی و ارزشمند از جامعه منبع باز است. در زیر ، من تجربیات خود را به عنوان مشارکت کننده شرح می دهم و مراحل کلیدی را که هرکسی می تواند برای مشارکت انجام دهد ، شرح می دهد.

چرا من شروع به مشارکت در Kubernetes کردم

مشارکت در یک پروژه منبع باز مانند Kubernetes اشکال مختلفی دارد: ارسال PR های کد ، به روزرسانی اسناد ، مسائل مربوط به تریاژ ، گزارش اشکالات ، بهبود تست ها ، مرور کد ، بررسی پیشنهادات بهبود Kubernetes (KEPs) و مشارکت در مدیریت انتشار Kubernetes . Kubernetes به لطف ساعات بیشماری که توسط همکاران فعلی و مشارکت کنندگان آینده مانند شما سپری شده است ، وجود دارد و رشد می کند.

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

من همیشه علاقه مند بودم که در پروژه های منبع باز مشارکت کنم و احساس می کردم اگر مشارکت در Kubernetes را شروع کنم ، در مورد سیستم های توزیع شده اطلاعات بیشتری کسب خواهم کرد. هیچ چیز به اندازه نوشتن کد برای آن تجربه ای به شما نمی دهد ، به این ترتیب من درگیر Kubernetes شدم و چرا انجام چنین کاری برای دیگران بسیار ارزشمند است.

نحوه کمک به Kubernetes به عنوان یک مبتدی

در اینجا برخی از اولین قدم هایی است که باید برای شروع مشارکت در Kubernetes انجام دهید.

1. به دنبال مستندات مربوطه باشید که برای مشارکت کنندگان موجود است

به طور معمول ، هنگامی که شما مشارکت کننده جدیدی در هر پروژه منبع باز هستید ، باید به دنبال هرگونه اسناد مرتبط برای مشارکت کنندگان باشید. معمولاً ، این به صورت یک فایل CONTRIBUTING.md یا چیزی مشابه است. README در ریشه یک repo نیز مکان خوبی برای شروع است. هر پروژه ای که به دنبال پرورش جامعه مشارکت کنندگان است باید این اطلاعات را به راحتی در اختیار مشارکت کنندگان جدید قرار دهد. مورد دیگری که باید مورد توجه قرار گیرد ، وسایل ارتباطی است که توسعه دهندگان در آن پروژه یا پروژه فرعی خاص از آن استفاده می کنند. به عنوان مثال ، Kubernetes به شدت به Slack و لیستهای پستی متکی است: مشترک کانالهای Slack و ایمیلهای مورد علاقه خود شوید ، به ویژه برای مناطق Kubernetes که قصد دارید در آنها مشارکت داشته باشید.

به عنوان یک مبتدی کامل برای Kubernetes به طور کلی ، و همچنین فردی که هیچ تجربه ای در مشارکت در پایگاه کد Kubernetes نداشت ، من مستقیماً به فایل CONTRIBUTING.md رفتم. این به خوبی مستند شده است و به من مستندات لازم را برای تنظیم محیط من برای شروع توسعه نشان داد.

2. مسائلی را که به شما علاقه دارند جستجو و فیلتر کنید

  • یافتن مشکلاتی برای کار: هنگامی که محیط برنامه نویس خود را تنظیم کردید ، می خواهید چیزی را پیدا کنید که روی آن کار کنید. هنگامی که من برای اولین بار شروع به کار کردم ، پس از اینکه محیط خود را تنظیم کردم ، به بررسی مسائل موجود در repo Kubernetes پرداختم. در GitHub ، هنگامی که مسائل مربوط به یک پروژه خاص را جستجو می کنید ، یک برچسب فیلترینگ وجود دارد که می تواند برای فیلتر کردن ” is:open is:issue label:”good first issue”” اعمال شود که نشان می دهد این مسئله می تواند توسط یک مبتدی کار شود. به عنوان مثال ، is:open is:issue label:”good first issue” ” در نوار جستجوی شماره GitHub لیستی از همه مسائل باز شده با برچسب “good first issue” را در اختیار شما قرار می دهد. برای فیلتر کردن بیشتر برای یک گروه علاقه مندی خاص (SIG) مانند sig/network ، عبارت “open is: issue”: برچسب ” is:open is:issue label:”good first issue”” را جستجو کنید: sig/network. از اینجا من توانستم اولین شماره خود را پیدا کنم.
  • رفع مشکلاتی که پیدا می کنید: پس از یافتن مشکلی ، باید به نگهبانان اطلاع دهید که قصد شما از کار روی آن چیست. اولین کاری که من انجام دادم این بود که در مورد GitHub بپرسم که آیا می توانم روی موضوعی که پیدا کردم کار کنم ، یعنی PR برای حذف تمام خطوط اضافی اضافی که به توابع Logf () منتقل می شوند. این شامل گذراندن کد در هر دو آزمون/e2e و test/e2e_node ، پیدا کردن مازاد خط جدید در تماس با Logf () و حذف آنها بود. این کار تمرین خوبی برای یادگیری نحوه مشارکت در پایگاه کد Kubernetes بود زیرا شامل تغییرات محلی ، ایجاد روابط عمومی در برابر شاخه اصلی و پرداختن به بازخورد بازبینی می شد.

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

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

به عنوان یک مشارکت کننده جدید ، هنگام کار روی اولین کارم احساس عدم اطمینان و سردرگمی کردم. من معتقدم راحت بودن با ندانستن راه حل برای رسیدگی به مسائلی که به شما محول شده و پیش بردن راه حل بسیار ارزشمند است. این بدان معنا نیست که در یک اتاق تاریک بنشینید و خودتان آن را حل کنید ، این بدان معناست که وقتی نیاز به توضیح مشکل دارید ، هنگامی که با اصطلاحات آشنا نیستید ، همانطور که در مثال قبلی اشاره کردم ، یا حتی وقتی که فقط می خواهم به راه حل پیشنهادی خود چشم دوخته باشم این نگرش متکی بر کار گروهی و همکاری در مواقع ضروری به شما کمک می کند تا در مشارکت منبع باز و به طور کلی در فناوری پیشرفت زیادی داشته باشید. به خاطر داشته باشید ، به عنوان محرک راه حلی شما باید مجموعه ای از اشکال زدایی و اطلاعاتی باشید که در تلاش برای حل مشکل در حین همکاری با دیگران به دست آورده اید. به طور معمول هیچ مهلت واقعی (مگر اینکه به طور دیگری اعلام شود) در ارتباط با این “اولین مسائل خوب” وجود ندارد ، بنابراین خیالتان راحت باشد تا زمانی که لازم است از پیشرفت مداوم در موضوع GitHub اطمینان حاصل کنید و افراد را در جریان نگه دارید ، دیگران را درگیر کنید در صورت نیاز کمک کند اگر در نهایت متوجه شدید که دیگر پهنای باندی برای کار روی آن ندارید ، در مورد موضوع مربوطه صحبت کنید و شخص دیگری آن را انتخاب خواهد کرد.

3. در پیدا کردن مسائل گیر کرده اید؟ سعی کنید سایه انتشار repo Kubernetes شوید

راه دیگر برای مشارکت از طریق به روزرسانی اسناد است ، که روشی متداول برای مشارکت کنندگان جدید است تا در یک پروژه منبع باز غیر از تغییرات کد مشارکت کنند. یکی از راههای جالبی که اخیراً در آن شرکت کرده ام ، برنامه سایه انتشار Kubernetes است ، برنامه ای که در آن افراد تازه وارد مدیریت انتشارات Kubernetes می توانند در یکی از بخشهای مختلف نسخه کار کنند. من روی پیشرفتهای Kubernetes 1.20 کار کردم. وظیفه ای که به من محول شد ، بررسی و ردیابی همه پیشنهادات Kubernetes Enhancements (KEPs) ، با کمک چند سایه دیگر و یک سرنخ بود. این به من اطلاعات زیادی در مورد روند KEP داد و به من اجازه داد تا با تعداد کمی از مشارکت کنندگان در این روند کار کنم. من این مسیر را به هر کسی که به دنبال راه اندازی مجدد شبکه و تأثیر خود در جامعه Kubernetes است ، بسیار توصیه می کنم.

مزایای عضویت در Kubernetes

تبدیل شدن به یک عضو Kubernetes نتیجه مشارکت مکرر و همکاری نزدیک با حداقل 2 عضو مختلف مختلف با قابلیت های بازبینی برای یک پروژه خاص در repo Kubernetes است. به عبارت دیگر ، در پروژه Kubernetes به 2 حوزه مختلف کمک زیادی کنید و شخصی را پیدا کنید که بتوانید از نزدیک با هر یک از آنها کار کنید. با گذشت زمان ، هنگامی که تجربه کسب می کنید و برخی روابط عمومی را تحت پوشش خود دارید ، از این افراد بپرسید که آیا می توانند برای عضویت از شما حمایت کنند.

یکی از مزایای اصلی عضویت در این است که بتوانید مسائل مربوط به خود را تعیین کرده و تأثیر بیشتری بر بخش های خاصی از کدی که روی آن کار می کنید داشته باشید. یکی دیگر از مزایای ملموس عضویت ، دریافت آسیب پذیری ها و مواجهه های مشترک Kubernetes (CVE) به محض تشخیص توسط جامعه است. این امر برای تیم vpsgol Kubernetes بسیار ارزشمند بود زیرا ما اطلاعات مربوط به این آسیب پذیری های امنیتی را قبل از عموم مردم دریافت می کنیم و به ما این امکان را می دهد که تلاش های ناخواسته برای به خطر انداختن پلت فرم ما و اطمینان از حفظ امنیت مشتریانمان در حین استفاده از DOKS و سایر محصولات مبتنی بر Kubernetes در بستر vpsgol را خنثی کنیم.

موانع مشترک در راه شما برای تبدیل شدن به یک مشارکت کننده Kubernetes

موانع زیادی وجود دارد که می تواند از پیشرفت در کمک به Kubernetes جلوگیری کند یا سرعت شما را کاهش دهد. مانع اصلی این است که اولین کد خود را وارد کنید. با توجه به تعداد زیاد مشارکت های روزانه و تعداد محدود مرورگران ، برخی از روابط عمومی می توانند ماه ها یا بیشتر بمانند. راه مقابله با این مسئله این است که مطمئن شوید در حال ارسال کدی هستید که در واقع مورد نیاز است. شما می توانید با پیوند دادن آن به یک مسئله موجود یا ایجاد مشکلی برای به دست آوردن اجماع از صاحبان کدی که می خواهید به آن مشارکت کنید ، مشکلی واقعی داشته باشید و تأییدکنندگان/بازبینان آن ناحیه از کد را درگیر کنید. شما قصد مشارکت دارید

1. کمک به کد بدون همکاری با جامعه

به یاد داشته باشید ، تعهدات رانندگی ممکن است به همان سرعتی که انتظار دارید بازبینی نشوند. نگهدارندگان یک پروژه فقط می توانند کارهای زیادی انجام دهند و زمینه های زیادی را در خود نگه دارند. وظیفه شما به عنوان مشارکت کننده است که روابط عمومی خود را تا آنجا که ممکن است بررسی کنید. برای روابط عمومی روابط عمومی خود توضیحات خوب و مکتوب ارائه دهید. اگر این یک تغییر بزرگ است ، مطمئن شوید که در مورد تغییر توافق شده است و در صورت لزوم آن را در روابط عمومی متعدد قرار دهید. در صورت گذشت زمان از زمان ایجاد روابط عمومی و پاسخ به موقع به نظرات در مورد روابط عمومی خود ، با احترام به نگهدارندگان در کانال ضعیف مناسب ضربه بزنید.

2. متواضع نبودن یا احترام به عنوان مشارکت کننده

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

بازبینی: چگونه می توان به عنوان یک مبتدی به عنوان منبع باز Kubernetes تبدیل شد

  1. منطقه ای از K8 ها را پیدا کنید که به شما علاقه دارد و “اولین شماره خوب” را با موضوعات دارای برچسب پیدا کنید تا بلافاصله روی آن کار کنید.
  2. به یاد داشته باشید ، ارتباط زیاد خوب است.
  3. وظیفه را به شیوه ای مثبت دنبال کنید.
  4. در طول مسیر به دیگران کمک کنید ، درست همانطور که در شروع کار می خواهید.

open source, خرید سرور, سرور مجازی, فروش vps, منبع باز

  • behnam gol mohamadi
  • ۰
  • ۰

 Multi-cloud و hybrid cloud:همه آنچه کسب و کار شما باید بداند

ورود به سایت

یافتن رویکرد رایانش ابری مناسب برای کسب و کار شما

ظهور رایانش ابری در کسب و کار انقلابی ایجاد کرده است. ابری به مشاغل این امکان را می دهد تا زمان و انرژی خود را بر روی فناوری ساختمان متمرکز کنند ، به جای حفظ زیرساخت ها ، که منجر به رونق نوآوری در استارتاپ ها و مشاغل کوچک شده است.

اگر این مطلب را می خوانید ، احتمالاً نیازی به تعریف رایانش ابری ندارید ، اما در اینجا فقط در مورد آن آمده است: رایانش ابری عبارت است از ارائه منابع محاسباتی به عنوان یک سرویس ، که توسط ارائه دهنده ابر و نه کاربر نهایی مدیریت می شود. این برخلاف نحوه عملکرد مشاغل ، یعنی خرید و مدیریت نرم افزار و سخت افزار خود است. اکنون که متعهد به ابر هستید ، گام بعدی این است که تفاوت ها و شباهت های استراتژی ابر ترکیبی و استراتژی های چند ابر را بشناسید و دریابید که کدام رویکرد برای تجارت شما مناسب است.

برای آشنایی بیشتر با رایانش ابری ، از جمله سابقه غنی آن ، مدلها و محیطهای مختلف و مزایای کلی تجارت ، این آموزش را از vpsgol بخوانید.

بلافاصله ،  hybrid cloud و multi-cloud به طرز مشکوکی مشابه هستند و مرتباً به جای یکدیگر استفاده می شوند. در حالی که هر دو سرویس های ابری را از بیش از یک منبع ارائه می دهند ، این کار را به روش های منحصر به فرد انجام می دهند و به تنظیمات مختلف ابر اشاره می کنند. برای مطالعه عمیق تر این مبحث به ادامه مطلب بروید.

رایانش hybrid cloud چیست؟

یک عامل عمده وجود دارد که رایانشhybrid cloud را از multi-cloud منحصر به فرد می کند: رایانش hybrid cloud زیرساخت های ابر خصوصی را در کنار ارائه دهندگان رایانش ابری عمومی شامل می شود. برای اینکه محاسبات ابری ترکیبی در نظر گرفته شود ، به طور کلی شامل یک جزء خصوصی مانند مرکز داده در محل است که مستقیماً توسط مشاغل با استفاده از آن مدیریت و نگهداری می شود.

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

وقتی مشاغل شروع به ترکیب چندین سرویس ابری عمومی در ترکیب می کنند ، این تعریف پیچیده می شود. وقتی چندین سرویس ابر عمومی در ارتباط با یکدیگر کار می کنند ، این چند ابر است .

رایانش multi-cloud چیست؟

راه اندازی رایانش multi-cloud در ساده ترین شکل به این معنی است که یک شرکت از چندین ارائه دهنده ابر عمومی برای انجام وظایف یا حجم کاری خاص استفاده می کند. به عنوان مثال ، یک ارائه دهنده برای حجم کار تحلیلی و یکی برای وب سایت های عمومی. همانطور که رامان شارما ، نایب رئیس بازاریابی محصول و برنامه DigitalOcean می گوید: “دلایلی که برای انتخاب راه اندازی چند ابر ارائه می شود متفاوت است-مدیریت ریسک ، اجتناب از قفل شدن و وابستگی به یک ارائه دهنده ، رعایت الزامات نظارتی و غیره.”

هر ارائه دهنده ابری مزایا و معایب خاص خود را دارد و با ترکیب چندین مورد ، یک کسب و کار می تواند از جنبه های منحصر به فرد هریک استفاده کند. به طور معمول این رویکرد برای توزیع منابع در محاسبات و کاهش احتمال از دست دادن داده ها یا آفلاین شدن استفاده می شود. راه اندازی چند ابر به ویژه برای مشاغل کوچک مفید است زیرا آنها را قادر می سازد تا هزینه ها و خدمات را با انتخاب ارائه دهندگان خاص ابر برای نیازهای خاص بهینه کنند ، نه یک ارائه دهنده بزرگ ابر که ممکن است شامل خدماتی باشد که مشاغل کوچک از آن استفاده نمی کنند.

برخی از مشاغل ممکن است از یک محیط hybrid وmulti-cloud استفاده کنند ، که در آن از یک ابر خصوصی علاوه بر چندین ابر عمومی استفاده می کنند. با این حال ، اگر یک کسب و کار فقط از یک سرویس ابری عمومی علاوه بر یک ابر خصوصی استفاده کند ، این تنها یک ابر ترکیبی محسوب می شود. تفاوت اصلی در اینجا این است که multi-cloud شامل بیش از یک ابر عمومی است

انتخاب گزینه ابر مناسب برای استارتاپ یا مشاغل کوچک شما

مشاغل کوچک کاندیدای ایده آل برای اتخاذ استراتژی hybrid وmulti-cloud هستند. بسیاری از مشاغل کوچک امروزی بومی ابر هستند ، به این معنی که در ابر متولد شده اند و هرگز زیرساخت خود را حفظ نمی کنند بلکه در عوض یک استراتژی چند ابر را اتخاذ می کنند. همانطور که شارما توضیح می دهد ، “اکثر شرکت های کوچکتر تقریباً بنا به ضرورت از معماری چند ابر استفاده می کنند. آنها دو نیاز دارند: 1) آنها می خواهند بر ساخت برنامه های خود تمرکز کنند و چرخ را دوباره اختراع نکنند. 2) آنها ابزارها و خدماتی را می خواهند که از نظر بهره وری و ROI در مناطق مربوطه بهترین تولید را داشته باشند. ” اغلب ، کار با ارائه دهندگان خدمات ابری خارجی نتیجه جستجوی نتایج مطلوب آنها با بودجه ای مناسب برای کسب و کار رو به رشد آنها است.

تنها با یک ارائه دهنده خدمات می توان مواردی را ذکر کرد ، اما این امر ممکن است نتواند به فناوری تخصصی که از ایده های نوآورانه و تکرار سرعت راه اندازی پشتیبانی می کند ، دسترسی پیدا کند.

وقتی نوبت به مسیر ترکیبی یا چند ابر می رسد ، تصمیم واقعاً در جایی است که منابع غیر ابری کسب و کار شما در کجا قرار دارد. اگر خرید و بهره برداری از یک ابر خصوصی در محل امکان پذیر است و به دلیل نیازهای منحصر به فردی که شرکت شما در زمینه امنیت یا پیکربندی نیاز دارد ، ترجیح داده می شود ، بنابراین ترکیبی راه درستی است. با این حال ، اگر این امر ضروری یا مطلوب نباشد ، استفاده از رویکرد چند ابر همچنان مزایای یکسانی را از نظر تقویت در برابر بلایا ، برخورد با رعایت و انعطاف پذیری به همراه خواهد داشت ، اما بدون استقلال همراه با داشتن ابر خصوصی. برای اکثر مشاغل کوچک و متوسط ​​، چند ابر انعطاف پذیری و قابلیت اطمینان لازم را بدون پیچیدگی و سرمایه گذاری زیرساختی مورد نیاز برای راه اندازی ابر ترکیبی فراهم می کند.

رایانش ابری همه چیز را در مورد توانمندسازی توسعه دهندگان و مشاغل برای ایجاد و کشف هرچه بیشتر گزینه ها می داند ، و ایجاد معماری محاسبات ترکیبی یا چند ابر تنها راه دیگری برای استفاده از چیزی است که ابر را بسیار قدرتمند می کند. برای کسب اطلاعات بیشتر در مورد خدمات ابری DigitalOcean و اینکه چگونه می توانند برای کسب و کار شما مفید باشند ، مجموعه محصولات ما را در اینجا مشاهده کنید.

hybrid cloudmulti-cloudخرید سرورخریدvpsرایانش ابریرایانش ابری ترکیبیسرور مجازیمحاسبات ابریهاست 

 

  • behnam gol mohamadi