چگونه یک REST API بدون سرور ایجاد کنیم
اگر یک توسعه دهنده Front-End هستید و می خواهید مهارت های خود را به نمایش بگذارید، اگر از صفحات GitHub یا Netlify برای نمایش برنامه های خود استفاده می کنید، ممکن است مشکل ساز شود.
در عوض، میتوانید بدون نیاز به سرور، مستقیماً در مرورگر یک REST API ایجاد کنید. با این کار، میتوانید مهارتهای خود را در برنامههایی که با یک Backend میزبانی شده در مکانهایی که نمیتوانید به سمت سرور دسترسی پیدا کنید، تعامل دارند، به نمایش بگذارید.
فهرست مطالب
چگونه یک کارگر خدماتی ثبت نام کنیم؟
چگونه یک پاسخ HTTP اولیه ایجاد کنیم
از کتابخانه Wayne استفاده کنید
Service Worker را نصب کنید
گفت ن API احراز هویت
احراز هویت را به React اضافه کنید
نسخه ی نمایشی کاملاً کار می کند
کارگر خدماتی چیست؟
API مرورگر که به شما امکان می دهد پاسخ های HTTP خالص به درخواست های HTTP را در مرورگر ایجاد کنید، Service Worker نامیده می شود. این API بیشتر برای رهگیری درخواستهای HTTP که از مرورگر نشات گرفتهاند و از حافظه پنهان ارائه میشوند ایجاد شده است.
این به شما امکان می دهد برنامه هایی به نام PWA ایجاد کنید که در صورت عدم اتصال به اینترنت کار کنند. پس می توانید از آنها در قطار استفاده کنید، جایی که ممکن است اینترنت ناپایدار داشته باشید. وقتی آفلاین هستید، درخواستهای HTTP را میتوان ذخیره کرد و وقتی دوباره آنلاین شد به سرور واقعی فرستاد.
اما این همه کاری نیست که کارگران خدمات می توانند انجام دهند. با آنها می توانید درخواست های HTTP ایجاد کنید که هرگز وجود نداشته اند. می تواند هر درخواست HTTP را رهگیری کند، برای مثال زمانی که یک تصویر را در برگه جدید باز می کنید یا از AJAX استفاده می کنید (مانند fetch API ).
چگونه یک کارگر خدماتی را ثبت نام کنیم؟
Service Worker باید در یک فایل جداگانه نوشته شود (اغلب sw.js
نامیده می شود، اما می توانید نام آن را هر چه می خواهید بنویسید).
محل آن فایل مهم است. باید در ریشه برنامه شما، اغلب در ریشه دامنه قرار داشته باشد.
برای ثبت نام یک سرویس دهنده، باید این کد را اجرا کنید:
if ('serviceWorker' in navigator) { var scope = location.pathname.replace(/\/[^\/]+$/, '/') navigator.serviceWorker.register('sw.js', { scope }) .then(function(reg) { reg.addEventListener('updatefound', function() { var installingWorker = reg.installing; console.log('A new service worker is being installed:', installingWorker); }); // registration worked console.log('Registration succeeded. Scope is ' + reg.scope); }).catch(function(error) { // registration failed console.log('Registration failed with ' + error); }); }
با این کار یک سرویسکار نصب میشود که میتواند شروع به رهگیری درخواستهای HTTP کند.
توجه: کارگر سرویس فقط با HTTPS و localhost کار می کند.
چگونه یک پاسخ HTTP اساسی ایجاد کنیم
API Service Worker بسیار ساده است – شما رویدادی به نام fetch
دارید
و شما می توانید با هر پاسخی به آن رویداد پاسخ دهید:
self.addEventListener('fetch', event => { const url = new URL(event.request.url); if (url.pathname === '/api/hello/') { const headers = { 'Content-Type': 'text/plain' }; const msg = 'Hello, Service Worker!' event.respondWith(textResponse(msg, headers)); } }); function textResponse(string, headers) { const blob = new Blob([string], { type: 'text/plain' }); return new Response(blob, { headers }); }
با این کد شما می توانید URL /api/hello/
را باز کنید و متن "Hello, Service Worker!"
به عنوان یک فایل متنی
همچنین، یک چیز مهم: اگر می خواهید از Service Worker بلافاصله پس از نصب آن استفاده کنید، باید این کد را اضافه کنید:
self.addEventListener('activate', (event) => { event.waitUntil(clients.claim()); });
به طور معمول، Service Worker درخواستها را تنها پس از اینکه صفحه را بهروزرسانی کنید، رهگیری میکند. این کد بلافاصله پس از نصب درخواست ها را می پذیرد.
توجه: با service worker، میتوانید درخواستهایی را که به دامنههای مختلف ارسال میشوند نیز رهگیری کنید. اگر برنامه خود را در صفحات GitHub دارید، می توانید درخواست های هر دامنه ای را رهگیری کنید. از آنجا که هیچ تحلیل دامنه وجود ندارد، این کد:
await fetch('https://example.com/api/hello').then(res => res.text())
همچنین باز خواهد گشت Hello, Service Worker!
.
نحوه ایجاد یک پروژه پایه
با ایجاد یک پروژه React با احراز هویت بسیار ساده کاربر، چیز مفیدتری ایجاد خواهید کرد.
توجه داشته باشید که این به هیچ وجه امن نیست، زیرا اطلاعات کاربر و رمز عبور در کد قابل مشاهده خواهد بود. اما می تواند نشان دهد که می دانید چگونه با یک API در React تعامل کنید.
راه اندازی Vite
ابتدا باید یک برنامه React ساده با Vite راه اندازی کنید.
برای استفاده از Vite، باید Node.js را نصب کرده باشید. اگر آن را ندارید، می توانید نحوه نصب آن را از این مقاله بخوانید.
سپس، باید این دستور را از ترمینال اجرا کنید:
npm create vite@latest
من نام auth
، React و JavaScript را انتخاب کردهام. این خروجی است که من دارم:
✔ Project name: … auth ✔ Select a framework: › React ✔ Select a variant: › JavaScript Scaffolding project in /home/kuba/auth... Done. Now run: cd auth npm install npm run dev
مرحله بعدی اصلاح فایل vite.config.js
است، پس Vite می داند که چگونه فایل سرویس کارگر را بسازد/
این فایل پیکربندی Vite ایجاد شده است:
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], })
شما باید فایل کانفیگ را تغییر دهید تا این کد را شامل شود:
import { join } from "node:path"; import { buildSync } from "esbuild"; export default defineConfig({ plugins: [ react(), { apply: "build", enforce: "post", transformIndexHtml() { buildSync({ minify: true, bundle: true, entryPoints: [join(process.cwd(), "src", "sw.js")], outfile: join(process.cwd(), "dist", "sw.js"), }); }, }, ] })
شما باید هر دو واردات را وارد کنید و می توانید پیکربندی موجود را با پیکربندی بالا جایگزین کنید. همچنین میتوانید کد موجود در بریسهای فرفری را به یک آرایه پلاگین اضافه کنید.
از کتابخانه Wayne استفاده کنید
سپس، باید یک فایل Service Worker با نام sw.js
ایجاد کنید. شما به جای نوشتن مسیرها از کتابخانه Wayne استفاده خواهید کرد. این کد را ساده می کند.
ابتدا باید Wayne را نصب کنید:
npm install @jcubic/wayne
سپس، میتوانید فایلی به نام sw.js
ایجاد کنید ( توجه: دایرکتوری "src"
در فایل vite.config.js
قرار دادهاید، پس باید فایل را در آن دایرکتوری ذخیره کنید).
import { Wayne } from '@jcubic/wayne'; const app = new Wayne(); app.get('/api/hello/', (req, res) => { res.text('Hello, Service Worker!'); });
این کد دقیقاً مانند مثال قبلی ما کار خواهد کرد.
Service Worker را نصب کنید
اکنون، آخرین کاری که برای راه اندازی سرویس کار خود باید انجام دهید، ثبت آن است. می توانید از کدی که قبلاً دیدید استفاده کنید، اما اکنون از یک کتابخانه برای این کار استفاده خواهید کرد.
ابتدا باید آن را نصب کنید:
npm install register-service-worker
و src/main.jsx
را با این کد به روز کنید:
import { register } from "register-service-worker"; register(`./sw.js`);
آخرین مورد این است که پروژه را با اجرای:
npm run build
توجه : حالت dev
با سرویس دهنده کار نمی کند - شما باید پروژه را بسازید.
دستورالعملهای راهاندازی یک Service Worker با Vite بر اساس این مقاله e.
تست روی وب سرور
برای تست پروژه خود می توانید از این دستور استفاده کنید:
npx http-server -p 3000 ./dist/
این یک سرور HTTP ساده ایجاد می کند که در آن می توانید برنامه خود را آزمایش کنید.
توجه : اگر فایل index.html
را در مرورگر باز کنید (مانند کشیدن و رها کردن)، سرویسکار کار نخواهد کرد. این به این دلیل است که پروتکل file://
دارای محدودیت های زیادی است. به همین دلیل به یک وب سرور نیاز دارید.
اگر برنامه را در مرورگر با باز کردن URL آزمایش کنید: http://127.0.0.1:3000
، کدی را اجرا می کند که سرویس دهنده را ثبت می کند و شما بلافاصله می توانید به نقطه پایانی جعلی HTTP ما دسترسی پیدا کنید: http://127.0.0.1:3000/api/hello/
. باید متن را نمایش دهد:
Hello, Service Worker!
توجه : برای ساده سازی تست، می توانید "http-server -p 3000 ./dist/"
را به فایل package.json در scripts
اضافه کنید:
"serve": "http-server -p 3000 ./dist/",
به یاد داشته باشید که package.json
یک فایل JSON است، پس اگر این آخرین اسکریپت باشد، نمیتوانید کاما انتهایی قرار دهید.
برای اینکه کار کند، باید بسته را نصب کنید:
npm install http-server
اکنون می توانید سرور را با npm run serve
اجرا کنید.
توجه : اگر به آدرس اینترنتی: http://127.0.0.1:3000/api/hello
دسترسی داشته باشید (در این مقاله می توانید 127.0.0.1 را بخوانید)، با خطای http-server
مواجه خواهید شد. این به این دلیل است که مسیری که در سرویسکار ایجاد کردهاید از یک اسلش انتهایی استفاده میکند. برای رفع این مشکل، می توانید یک تغییر مسیر اضافه کنید:
app.get('/api/hello', (req, res) => { res.redirect(301, req.url + '/'); });
نحوه گفت ن React Authentication
اکنون، پس از اینکه همه چیز را تنظیم کردید، می توانید یک نقطه پایانی احراز هویت واقعی اضافه کنید و آن را با برنامه React خود متصل کنید.
یک توکن JWT ایجاد کنید
ما از یک توکن JWT محبوب برای احراز هویت استفاده خواهیم کرد. در این مقاله می توانید اطلاعات بیشتری در مورد آنها بخوانید.
ابتدا باید یک کتابخانه JWT نصب کنید:
npm install jose
سپس، باید یک فایل جدید به نام jwt.js
در دایرکتوری src
ایجاد کنید:
import { SignJWT, jwtVerify } from 'jose'; const secret = new TextEncoder().encode( 'cc7e0d44fd473002f1c42167459001140ec6389b7353f8088f4d9a95f2f596f2' ); const alg = 'HS256'; const jwt = { sign: (payload) => { return new SignJWT(payload) .setProtectedHeader({ alg }) .setIssuedAt() .setIssuer('https://freecodecamp.org') .setAudience('https://freecodecamp.org') .setExpirationTime('2h') .sign(secret) }, verify: async (token) => { const { payload } = await jwtVerify(token, secret, { issuer: 'https://freecodecamp.org', audience: 'https://freecodecamp.org', }); return payload; } }; export default jwt;
این کد یک ماژول ES است که از کتابخانه نشانه jose
JWT برای ایجاد یک نشانه جدید به jwt.sign
استفاده می کند. با jwt.verify
درستی توکن را تأیید میکند، و همچنین بار را برمیگرداند، پس میتوانید هر چیزی را که در توکن ذخیره میکنید استخراج کنید.
می توانید اطلاعات بیشتری در مورد کتابخانه jose
از مستندات بخوانید - پیوندهای اسناد در README هستند .
توجه : به دلیل محدودیت Service Worker، ما نمیتوانیم احراز هویت واقعی واقعی را ایجاد کنیم، جایی که رمز دسترسی در یک کوکی ذخیره میشود (سرویسکار اجازه ایجاد کوکیها را نمیدهد) و از نشانههای تازهسازی برای بهروزرسانی نشانه دسترسی استفاده میکنیم.
گفت ن API احراز هویت
اکنون می توانید از توابع قبلی برای ایجاد یک نقطه پایانی API استفاده کنید:
import jwt from './jwt'; app.post('/api/login', async (req, res) => { const { username, password } = await req.json() ?? {}; if (username === 'demo' && password === 'demo') { const token = await jwt.sign({ username }); res.json({ result: token }); } else { res.json({ error: 'Invalid username or password' }); } });
این کد تأیید می کند که نام کاربری و رمز عبور صحیح است (هر دو برابر با "demo"
)، و یک توکن JWT جدید ایجاد می کند. اگر نام کاربری یا رمز عبور صحیح نباشد، با خطا مواجه می شود.
احراز هویت را به React اضافه کنید
شما یک React App را با Vite ایجاد کردید، پس باید از JSX برای اضافه کردن منطق احراز هویت front-end استفاده کنید.
ابتدا یک تابع کمکی ایجاد می کنید که با Fetch API یک درخواست HTTP را به نقطه پایانی /api/login
ارسال می کند:
function login(username, password) { return fetch('/api/login', { method: 'post', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }).then(res => res.json()); }
بعد، شما باید یک فرم اصلی ایجاد کنید:
<form> <div> <label for="user">username</label> <input id="user" /> </div> <div> <label for="password">password</label> <input id="password" type="password" /> </div> <button>login</button> </form>
و کمی استایل اضافه کنید:
form { display: inline-flex; flex-direction: column; gap: 10px; align-items: flex-end; } label::after { content: ":"; } label { width: 100px; display: inline-block; text-align: right; margin-right: 10px; }
در مرحله بعد، به یک تابع احراز هویت نیاز دارید که آن را به رویداد onSubmit
اضافه کنید.
شما از دو متغیر حالت برای نشانه و خطا استفاده خواهید کرد:
function App() { const [token, setToken] = useState(null); const [error, setError] = useState(null); async function auth(event) { event.preventDefault(); const res = await login(username, password); if (res.result) { setToken(res.result); } else if (res.error) { setError(res.error); } }
برای دریافت نام کاربری و رمز عبور از فرم می توانید از refs استفاده کنید. شما همچنین می توانید فرم را فقط زمانی نمایش دهید که نشانه تنظیم نشده باشد:
function App() { const [token, setToken] = useState(null); const [error, setError] = useState(null); const userRef = useRef(); const passwordRef = useRef(); async function auth(event) { event.preventDefault(); const username = userRef.current.value; const username = passwordRef.current.value; const res = await login(username, password); if (res.result) { setToken(res.result); } else if (res.error) { setError(res.error); } } return ( <div> <div className="card"> {!token && ( <form onSubmit={auth}> <div> <label for="user">username</label> <input id="user" ref={userRef}/> </div> <div> <label for="password">password</label> <input id="password" ref={passwordRef} type="password"/> </div> <button>login</button> </form> )} {error && <p className="error">{ error }</p>} </div> </div> ); }
اکنون می توانید برنامه را تست کنید. اگر نام کاربری و رمز عبور را تایپ کنید، بازنشانی نمی شوند.
می توانید با تنظیم مقدار ref به یک رشته خالی در انتهای تابع، آن را برطرف کنید:
userRef.current.value = ''; passwordRef.current.value = '';
یک خطای دیگر وجود دارد. اگر نام کاربری یا رمز عبور را اشتباه وارد کنید، با خطا مواجه خواهید شد. اما پس از آن، اگر رمز عبور صحیح را تایپ کنید، خطا حذف نمی شود. برای رفع این مشکل، باید حالت خطا را هنگام تنظیم توکن بازنشانی کنید:
async function auth(event) { event.preventDefault(); const username = userRef.current.value; const username = passwordRef.current.value; const res = await login(username, password); if (res.result) { setToken(res.result); setError(null); } else if (res.error) { setError(res.error); } userRef.current.value = ''; passwordRef.current.value = ''; }
کار بعدی که می توانید انجام دهید این است که نام کاربری را از توکن استخراج کنید. با این کار همچنین تأیید میشود که توکن در برنامه React شما درست است. برای اجرای کد هنگام تغییر توکن، باید از قلاب useEffect
استفاده کنید:
import jwt from './jwt'; // ... const [username, setUsername] = useState(null); useEffect(() => { jwt.verify(token).then(payload => { const { username } = payload; setUsername(username); }).catch(e => { setError(e.message); }); }, [token]); // ...
اگر این کد را اجرا کنید، با یک خطا مواجه می شوید: Compact JWS must be a string or Uint8Array
.
دلیل آن این است که قلاب useEffect
زمانی فعال می شود که توکن null
باشد. قبل از تأیید، باید تحلیل کنید که آیا نشانه تنظیم شده است یا خیر:
useEffect(() => { if (token !== null) { jwt.verify(token).then(payload => { const { username } = payload; setUsername(username); }).catch(e => { setError(e.message); }); } }, [token]);
در مرحله بعد، می توانید نام کاربری را پس از ورود کاربر نمایش دهید:
{token && ( <div> <p>Welcome {username}</p> </div> )}
مراحل بعدی
آخرین کاری که می توانیم انجام دهیم این است که توکن را در localStorage
ذخیره کنیم و یک دکمه خروج اضافه کنیم. اما این به عنوان یک تمرین به خواننده سپرده می شود.
شما می توانید در مورد localStorage
از این مقاله freeCodeCamp بخوانید.
می توانید این را بهبود ببخشید و نقاط پایانی بیشتری اضافه کنید، مانند دریافت داده های واقعی که در یک فایل sw.js
ذخیره خواهید کرد. شما می توانید داده ها را در IndexedDB ذخیره کنید، پس مانند یک برنامه واقعی پایدار خواهد بود. در مورد IndexedDB از این مقاله بیشتر بخوانید.
IndexedDB API خیلی خوبی ندارد، اما کتابخانه هایی وجود دارند که انتزاع را در بالای آن اضافه می کنند. مورد علاقه من کتابخانه SQL AlaSQL و idb توسط Jake Archibald است.
نسخه ی نمایشی کاملاً کار می کند
کد منبع کامل در GitHub در مخزن jcubic/react-wayne-auth موجود است. میتوانید یک نسخه نمایشی کارآمد را در صفحات GitHub آزمایش کنید.
اگر این مقاله را دوست دارید، ممکن است بخواهید من را در رسانه های اجتماعی دنبال کنید: ( توئیتر/X و/یا لینکدین ) و همچنین وب سایت شخصی من را تحلیل کنید.
ارسال نظر