دست زدن به خطا و میانه – جامعه dev

- متغیرهای محیطی
- میانه
- اعتبار سنج
- خطای خط میانی
در گزیده قبلی ، اعتبار سنجی ، احراز هویت و مجوز با کتابخانه ها ، ما از Joi برای اعتبار سنجی درخواست و JSONWeBtoken برای تولید نشانه های AUTH استفاده کردیم.
متغیرهای محیطی
هنگامی که ما JWT را برای نشانه های نویسنده خود تولید می کردیم ، یک راز را پشت سر گذاشتیم. معمولاً ، طبق توصیه ، راز به عنوان یک متغیر محیطی منتقل می شود. متغیر محیطی یک مقدار پیکربندی (مقدار کلید) است که از سیستم عامل به آن منتقل می شود یا به آن دسترسی پیدا می کند. با این کار ، ما می توانیم داده ها را به API خود منتقل کنیم بدون اینکه مقدار پیکربندی را در API تعبیه کنیم (به عنوان یک تحت اللفظی در معرض).
کنسول/ترمینال خود را باز کنید و وارد شوید ، node
بشر روی گره جایگزین ، وارد شوید ، process.env
بشر این همان چیزی است که من می بینم:
Users-MacBook-Pro:expense-tracker-simple-api user$ node
Welcome to Node.js v22.12.0.
Type ".help" for more information.
> process.env
{
NVM_INC: '/Users/user/.nvm/versions/node/v22.12.0/include/node',
TERM_PROGRAM: 'vscode',
NVM_CD_FLAGS: '',
TERM: 'xterm-256color',
SHELL: '/bin/bash',
HOMEBREW_REPOSITORY: '/opt/homebrew',
TMPDIR: '/var/folders/p8/60cwd37n1ds64r381rjkt8g80000gn/T/',
TERM_PROGRAM_VERSION: '1.97.2',
ORIGINAL_XDG_CURRENT_DESKTOP: 'undefined',
MallocNanoZone: '0',
NVM_DIR: '/Users/user/.nvm',
...
}
>
ما می توانیم با انجام مقداری مقدار پیکربندی به API گره خود منتقل کنیم KEY_1=VALUE_1 KEY_2=VALUE_2 node
بشر وقتی این دستور را اجرا کردیم ، دیدیم که این مقادیر کلیدی تازه اضافه شده این بار به عنوان بخشی از پاسخ ما ظاهر می شوند.
NB: شما باید از repr node استفاده کنید
control + C
Users-MacBook-Pro:expense-tracker-simple-api user$ KEY_1=VALUE_1 KEY_2=VALUE_2 node
Welcome to Node.js v22.12.0.
Type ".help" for more information.
> process.env
{
KEY_1: 'VALUE_1',
KEY_2: 'VALUE_2',
NVM_INC: '/Users/user/.nvm/versions/node/v22.12.0/include/node',
NVM_CD_FLAGS: '',
TERM: 'xterm-256color',
SHELL: '/bin/bash',
HOMEBREW_REPOSITORY: '/opt/homebrew',
TMPDIR: '/var/folders/p8/60cwd37n1ds64r381rjkt8g80000gn/T/',
TERM_PROGRAM_VERSION: '1.97.2',
ORIGINAL_XDG_CURRENT_DESKTOP: 'undefined',
MallocNanoZone: '0',
NVM_DIR: '/Users/user/.nvm',
...
}
>
شما باید ببینید KEY_1: 'VALUE_1'
وت KEY_2: 'VALUE_2'
بشر
برای دیدن اینکه چگونه این کار در API ما کار خواهد کرد ، می توانیم یک فایل موقت ایجاد کنیم و محتوای آن را چاپ کنیم
process.env
ما می توانیم با استفاده از کلید به مقادیر منتقل شده دسترسی پیدا کنیم. بنابراین اگر یک راز را پشت سر گذاشتیم ، SECRET="some secret" node temp_file.js
و ما وارد می شویم ، console.log(process.env.SECRET)
بشر خواهیم دید که خروجی با مقدار منتقل شده مطابقت دارد.
SECRET="some secret" node temp_file.js
some secret
این رویکرد غیر عملی می شود به همین ترتیب ما از a استفاده می کنیم .env
پرونده env = environment
بشر یک فایل را در ریشه پروژه خود ایجاد کنید و آن را صدا کنید .env
بشر تمام پیکربندی های ارزش کلید خود را در آنجا عبور دهید.
پیش از nodejs 20
، ما برای دسترسی به ما به یک کتابخانه نیاز داشتیم .env
مقادیر بعداً در مورد آن بحث خواهیم کرد. با این حال ، برای همه نسخه های فوق ، تنها کاری که باید انجام دهیم این است که تصویب شود --env-file
پرونده و مقدار آن را روی مسیر تنظیم کنید .env
مسیر پرونده: node --env-file=.env temp_file.js
node --env-file=.env temp_file.js
some secret
اگر به غیر از مقادیر واقعی تصویب شده ، چیزی را دریافت می کنید ، می توانیم این کار را با کتابخانه ای به نام Dotenv حل کنیم. شما باید بدانید که چگونه بسته ها را در Nodejs نصب کنید. نام بسته است dotenv
بشر
npm i dotenv
در پرونده ما می توانیم اضافه کنیم ، require("dotenv/config")
، در بالای پرونده خود. این بار ما فقط اجرا می کنیم ، node temp_file.js
require("dotenv").config();
// if the above doesn't work for you, try the approach below
// require("dotenv/config")
console.log(process.env.SECRET);
اگر با git آشنا هستید ، حتماً مسیر را به سمت آن ایجاد کرده و عبور دهید
.env
به.gitignore
برای شما که با Git آشنا نیستید ، Git ابزاری برای مدیریت کد منبع شماست..env
مقادیر پیکربندی واردات را در اختیار دارد و در معرض آنها قرار می گیرد و منجر به بهره برداری بالقوه می شود. مراقب باشید اما وحشت نکنید.
با استفاده از این اطلاعات ، اکنون شما ایجاد یک .env
پرونده هر مقدار پیکربندی را منتقل می کند و به آن طبق برنامه دسترسی پیدا می کند.
فقط برای ایمن بودن ، بررسی کنید که آیا مقدار است
undefined
و به درستی پاسخ دهید – در مورد تفاوت بین NULL و تعریف شده بخوانیداز آنجا که ما مجبور نیستیم خودمان را بسازیم
.env
باز ، ما ایجاد می کنیمsample.env
فقط کلیدها را ثبت کرده و عبور دهید تا توسعه دهندگان بدانند که چه چیزی.env
پرونده انتظار دارد
میانه
ما بحث کرده ایم که کنترل کننده چیست. این یک یادآوری است ، و شاید اگر ما در مورد آن بحث نکرده ایم ، یک کنترلر یک تابع (روش) است که درخواست ها را کنترل می کند ، از فرم ها است:
[async] function FunctionName(requestObject, responseObject) {
// do something on the request
// return a response
}
نکته ای که من می خواهم درک کنیم این است که کنترل کننده ها متقاضی درخواست کننده هستند.
متقاضیان درخواست معمولاً به دو شکل هستند:
به طور خلاصه ، یک واسطه نرم افزاری درخواست کننده است که بین یک مسیر و یک کنترلر قرار دارد.
router.method("/some route", middlewares, controller);
یک میان افزار به این شکل است:
[async] function FunctionName(requestObject, responseObject, nextMiddleware) {
// do something on the request
// return a response if there is an error
// else go to the next middleware
}
تنها تفاوت در اینجا این است که یک پارامتر سوم دارد که لقب دارد ، next
، بیشتر اوقات next
در اینجا میان افزار بعدی در خط لوله وجود دارد (کنترلر مانند یک واسطه است).
یک واسطه به شیء درخواست و پاسخ دسترسی دارد و به همین ترتیب می تواند درخواست تغییر (حذف ، افزودن یا به روزرسانی) بار را رهگیری کند. در ما index.js
پرونده ، موارد زیر را داریم:
// parse request body as json
app.use(express.json());
// register routers
app.use(userEndpoints);
app.use(expendituresEndpoints);
-
app.use(express.json());
واسطه ای است که بدنه درخواست را به JSON تجزیه می کند -
app.use(userEndpoints);
که نقاط انتهایی کاربر را در برنامه اصلی قرار می دهد -
app.use(expendituresEndpoints);
که نقاط پایانی هزینه ها را در برنامه اصلی قرار می دهد
بیایید یک میان افزار ایجاد کنیم که موارد زیر را در مورد یک درخواست ثبت کند:
- زمان
- روش HTTP
- و مسیر بازدید مشتری را مسیریابی کنید
بیشتر این اطلاعات را می توان در شی درخواست یافت.
req.method
وتreq.originalUrl
بشر
// add console logging middleware
app.use((req, res, next) => {
const log = `${req.method} :: ${
req.originalUrl
} - ${new Date().toISOString()}`;
console.log(log);
return next();
});
این وسط را بعد از (یا زیر) قرار دهید app.use(express.json());
بشر
نکته ای که باید بدانید این است که Middlewares به ترتیب تنظیم شده اجرا می شوند.
app.use(express.json());
قبل از ضربه هر نقطه پایانی می آید ، بنابراین داده ها قبل از رسیدن به آن مسیر تجزیه می شوند.
با توجه به این نکته ، اکنون می توانیم وسط نرم افزار را بالاتر از روترهای ثبت شده (یا مسیرها) قرار دهیم ، اما در زیر app.use(express.json());
بشر
در مسیرهای محافظت شده ، مسیرهایی که به JWT Auth نیاز داشتند، ما می توانیم یک میانی نرم افزاری داشته باشیم که بررسی کند که آیا درخواست ورودی دارای نشانه JWT است یا خیر.
اگر تعجب می کنید که چه اتفاقی می افتد یا چه کاری باید انجام شود در صورت عدم وجود JWT ، باید یک پیام یا پاسخ خطا مناسب را برگردانید. موضوع پاسخ ، سر، در معرض شما قرار دارد.
ظاهراً ، هیچ یک از مسیرهای کاربر نیاز به JWT Auth ندارد ، با این حال ، هزینه ها انجام می دهند. بیایید میان افزار دیگری ایجاد کنیم که در صورت درخواست JWT بررسی کند.
بررسی کردن
authorize
عملکرد نحوه دسترسی به JWT
آیا این قطعه کد را دیده اید و چند نفر را دیده اید؟ حدود پنج؟
const authReponse = authorize(req.headers.authorization);
if (!authReponse.isAuthorized) {
return res.status(200).json({
success: false,
message: "Unauthorized, please log in",
});
}
وقتی مسیرهای بیشتری داشته باشیم که به JWT Auth نیاز داشته باشیم ممکن است بیشتر باشد.
این بار قصد داریم تابعی را برای این میان افزار ایجاد کنیم. دستان خود را روی آن امتحان کنید.
/* checks the header of the incoming request if there is a jwt */
function hasJwt(req, res, next) {
// implementation before calling the next function
}
و برای انجام احراز هویت ، میانی دیگری ایجاد کنید.
/* authenticates and authorizes user */
function isAuthorized(req, res, next) {
// implement user authentication here
}
فایلی به نام ایجاد کنید
middlewares.js
و اولین میانی نرم افزار را برای ورود به درخواست (جزئیات) به عنوان نامگذاری کنیدlogRequest
بشر
(req, res, next)
تا آنجا که ترتیب (موقعیت) پارامترها رعایت می شود ، می تواند هر اسامی داشته باشد.
در اینجا چیزی است که من دارم یا آنچه شما باید به نظر برسید:
// middlewares.js;
const jwt = require("jsonwebtoken");
/* Logs the request method, route and the time the request was made */
function logRequest(req, res, next) {
const log = `${req.method} :: ${
req.originalUrl
} - ${new Date().toISOString()}`;
console.log(log);
return next();
}
/* checks the header of the incoming request if there is a jwt */
function hasJwt(req, res, next) {
const authorization = req.headers.authorization;
if (!authorization) {
return res.status(200).json({
success: false,
message: "Unauthorized, No auth token found",
});
}
return next();
}
function isAuthorized(req, res, next) {
const authorization = req.headers.authorization;
const JWT_SECRET = process.env.SECRET;
if (!JWT_SECRET) {
return res.status(200).json({
success: false,
message: "Something went wrong",
});
}
const { userId, email } = jwt.verify(authorization, JWT_SECRET);
// now we can fetch the user with email and userId
const isAuthenticUser = users.find(
(user) => user.email === email && user.id === userId
);
if (!isAuthenticUser) {
return res.status(200).json({
success: false,
message: "Unauthorized, No user matched",
});
}
req.user = { userId, email };
return next();
}
module.exports = { logRequest, hasJwt, isAuthorized };
req.someProperty = someValue
، کجاsomeProperty
مقدار کلیدی موجود را بازنویسی نمی کند.
ما پیام دهنده درخواست بعدی را ارسال می کنیم و به همان شیوه به آن دسترسی پیدا می کنیم. در چرخه زندگی درخواست ، شی درخواست در کل به اشتراک گذاشته می شود.
اکنون می توانیم موارد را به روز کنیم list expenditures
مسیر برای اضافه کردن hasJwt
وت isAuthorized
بشر
// list expenditures
app.get("/expenditures", (req, res) => {
// extra auth token from headers
const authReponse = authorize(req.headers.authorization);
if (!authReponse.isAuthorized) {
return res.status(200).json({
success: false,
message: "Unauthorized, please log in",
});
}
// parse the auth user id
const { userId } = authReponse;
// ====================
// get the query string and check if it is not a number or something
// that can be a number else set a default filter value of 0
let amountMoreThan = Number(req.query.amountMoreThan);
if (isNaN(amountMoreThan) || amountMoreThan < 0) {
amountMoreThan = 0;
}
return res.json({
success: true,
data: expenditures.filter(
(row) => row.userId === userId && row.amount > amountMoreThan
),
});
});
می شود
// list expenditures
app.get("/expenditures", hasJwt, isAuthorized, (req, res) => {
// parse the userId and email from the req.user
const { userId /*, email */ } = req.user;
// ====================
// get the query string and check if it is not a number or something
// that can be a number else set a default filter value of 0
let amountMoreThan = Number(req.query.amountMoreThan);
if (isNaN(amountMoreThan) || amountMoreThan < 0) {
amountMoreThan = 0;
}
return res.json({
success: true,
data: expenditures.filter(
(row) => row.userId === userId && row.amount > amountMoreThan
),
});
});
نکته اینجاست که می توانیم بین مسیر و کنترل کننده درخواست (کنترل کننده) یک واسطه (ها) اضافه کنیم.
یک تمرین دیگر در اینجا انجام همین کار برای بقیه است.
- اضافه کردن
hasJwt, isAuthorized,
- سپس حذف کنید
// extra auth token from headers
const authReponse = authorize(req.headers.authorization);
if (!authReponse.isAuthorized) {
return res.status(200).json({
success: false,
message: "Unauthorized, please log in",
});
}
// parse the auth user id
const { userId } = authReponse;
// parse the auth user id
const { userId } = req.user;
اگر تعجب می کنید کجا
req.user
از آن است ، پس از آن است (یا تنظیم شده است)isAuthorized
واسطه
ورود به سیستم را امتحان کنید ، و یک ورود به سیستم را مشاهده خواهید کرد ، POST :: /users/login - 2025-03-02T14:23:59.310Z
بشر تاریخ ممکن است متفاوت باشد اما شما باید یک خروجی مشابه داشته باشید.
با استفاده از JWT به دست آمده در هزینه های پایانی هزینه ها موارد زیر را شامل می شود:
-
POST :: /expenditures - 2025-03-02T14:28:17.173Z
-
GET :: /expenditures - 2025-03-02T14:28:41.074Z
در این مرحله ، مسیرهای هزینه شما باید کم و بیش شبیه به نظر برسد
router.get("/route", hasJwt, isAuthorized, (req, res) => {
/* */
});
یک مورد که شما متوجه می شوید این است
hasJwt, isAuthorized,
در تمام مسیرها ظاهر می شود و ما نیز ممکن است آن را در ریشه نقطه پایانی هزینه های خود قرار دهیم.
برای مبتدیان این خوب است ، اما از آنجا که برای همه مسیرهایی که می توانیم پیش برویم ، آن را در نقطه پایانی ریشه قرار می دهیم.
در آنجا موقعیت های منحصر به فردی وجود داشت که میان افزار مسئله ای باشد ، می توانیم تصمیم بگیریم که آنها را در مسیر آسیب دیده قرار دهیم یا حذف کنیم.
بنابراین ما می توانیم آن را به عنوان ،
app.use(hasJwt, isAuthorized, expendituresEndpoints);
یا
router.get("/route", hasJwt, isAuthorized, (req, res) => {
/* some expenditure request handling */
});
اولی بیشتر استقبال می کند اما هر یک از آنها کار می کند.
ما می توانیم پرونده فهرست خود را به روز کنیم تا پرونده فهرست خود را از آن به روز کنیم
// register routers
app.use(userEndpoints);
app.use(hasJwt, isAuthorized, expendituresEndpoints);
به
// register routers
app.use("/users", userEndpoints);
app.use("/expenditures", hasJwt, isAuthorized, expendituresEndpoints);
و ما وارد خواهیم شد userEndpoints
وت expendituresEndpoints
و سپس نقاط پایانی پایه (مسیرها) را بردارید. app.delete("/expenditures/:id",...)
می شود ، app.delete("/:id",...)
بشر
اعتبار سنج
ما در حال حاضر با مفهوم اعتبار سنجی آشنا هستیم ، با نوشتن آن خودمان یا استفاده از کتابخانه ای مانند جوی. ما همچنین می دانیم که می توانیم داده ها را از طریق هدرها ، رشته های پرس و جو ، درخواست پارامترهای و بدن به API خود منتقل کنیم. بنابراین در اینجا ، ما می توانیم بگوییم که انتظار می رود اعتبارسنجی انجام شود (مانند این ، داده های آن را از آن بگیرید).
بیایید از ثبت نام برای یک مطالعه موردی استفاده کنیم.
const { email, password } = req.body;
const validationResponse = authValidationSchema.validate({
email,
password,
});
if (validationResponse.error) {
return res.status(200).json({
success: false,
message: validationResponse.error.message,
// message: validationResponse.error.details[0].message,
});
}
- داده های اعتبار سنجی از بدن آمده است:
const { email, password } = req.body;
بشر - ما تماس می گیریم
validate
روش یک طرح جوی ،const validationResponse = authValidationSchema.validate({ ...})
- گرفتن برخی از داده ها
یک وسط نرم افزار معمولی به این شکل است:
[async] function FunctionName(requestObject, responseObject, next) {
// do something on the request
// return a response
}
که همه ما باید در این مرحله بدانیم. نکته اینجاست که می توانیم داده ها را به میان افزار منتقل کنیم. ما تابعی را ایجاد خواهیم کرد که کنترل کننده درخواست را برگرداند.
function FunctionName(parameters) {
return function (req, res, next) {
/* do something */
return next();
};
}
در مورد ما ، پارامترهای عملکرد طرح اعتبار سنجی مورد علاقه خواهند بود و در آنجا می خواهیم داده ها را از (برای اعتبار سنجی) استخراج کنیم. در اینجا درخواست املاک می تواند باشد: بدنهبا پارامتبا پرسش یا عناوینبشر
ما می توانیم این عملکرد را به هر نامی که می خواهید فراخوانی کنیم ،
validation, validationMiddleware, etc
/* validation middleware: takes schema and a request property*/
function validation(schema, requestProperty) {
return function (req, res, next) {
const validationResponse = schema.validate(req[requestProperty]);
if (validationResponse.error) {
return res.status(200).json({
success: false,
message: validationResponse.error.message,
// message: validationResponse.error.details[0].message,
});
}
return next();
};
}
این باید آشنا به نظر برسد.
- ما اعتبار سنجی را می گیریم
schema
و آن را به عنوان یک آرگومان منتقل کنید و همچنین داده ها را از طریق و از طریق آن تهیه کنیدrequestProperty
بشر -
req[requestProperty]
، اگرrequestProperty
آیا بدن نتیجه خواهد گرفتreq["body"]
کدام استreq.body
بشر
در ثبت نام کردن مسیر به نظر می رسد app.post("/signup", (req, res) => {...})
بشر با اطلاعات جدیدی که اکنون داریم ، اعتبار سنجی را اضافه خواهیم کرد که از طرحواره عبور می کند و کنترلر را به روز می کند تا اعتبار سنجی را حذف کند (در کنترلر انجام شده است تا از کنترلر فقط برای منطق مورد نیاز استفاده شود).
در sign up
مسیر باید شبیه باشد:
app.post("/signup", validation(authValidationSchema, "body"), (req, res) => {
/* */
});
ما می توانیم همان refactor را در ورودبشر
app.post("/login", validation(authValidationSchema, "body"), (req, res) => {
/* */
});
به عنوان یک تمرین ، مسیرهای هزینه را برای استفاده از میان افزار اعتبار سنجی عمومی و عبور از طرحواره مناسب به آن ، بازپرداخت کنید. ما حتی می توانیم با اعتبار سنجی پارامترهای درخواست و نمایش داده های رشته ای ، مایل اضافی را طی کنیم.
اینگونه است که نقطه پایانی ما به نظر می رسد:
/* /users */
app.post("/signup", validation(authValidationSchema, "body"), (req, res) => {
/* */
});
app.post("/login", validation(authValidationSchema, "body"), (req, res) => {
/* */
});
/* /expenditures*/
app.get("/", validation(expenditureQuerySchema, "query"), (req, res) => {
/* */
});
app.get("/:id", validation(IdValidationSchema, "params"), (req, res) => {
/* */
});
app.post("/", validation(createExpenseSchema, "body"), (req, res) => {
/* */
});
app.put(
"/:id",
validation(IdValidationSchema, "params"),
validation(updateExpenseSchema, "body"),
(req, res) => {
/* */
}
);
app.delete("/:id", validation(IdValidationSchema, "params"), (req, res) => {
/* */
});
خطای خط میانی
امیدوارم شاید ، شما متوجه شده باشید که ما این نوع خطا را بدست آورده ایم:
-
TokenExpiredError: jwt expired
-
JsonWebTokenError: invalid token
در بعضی از نقاط موظف است. به هر حال ، ما باید به طور کلی خطاهایی را که ممکن است در مصرف API (ادغام) ما رخ دهد ، انجام دهیم. یک راه برای رسیدگی به خطاها استفاده از آن است try-and-catch
بشر ما در مورد بحث کردیم try-and-catch
در JavaScript Essentials: قسمت 5.
ما کدی را که می دانیم می پیچیم ممکن است خطایی در یک ایجاد کند try-and-catch
در صورت بروز خطایی ، پیام پیش فرض را بازگردانید و سپس برخی از پیام های پیش فرض را برگردانید. مثال:
function someRequestHandler(req, res, next) {
try {
/* Do something */
} catch (error) {
return res.status(200).json({
success: false,
message: "Something went wrong please, try again later.",
});
}
}
ما حدود شش مسیر داریم و برای شروع می توانیم درست همانطور که در بالا نشان داده شد ، خطاها را برطرف کنیم. مواردی وجود دارد که موارد فوق اشکالی ندارد. با این حال ، در مورد یک برنامه تجاری ، وقتی خطایی رخ می دهد ، ما می خواهیم آن را درست بدانیم و حل کنیم؟ نکته منفی با اجرای فوق این است که ممکن است ردیابی/پشته خطا را از دست بدهیم و به ما اطلاع می دهد که چه چیزی و در کجا خطایی رخ داده است. نکته این است که ما نمی دانیم چه چیزی باعث خطا شده است. اکسپرس همان چیزی است که ما می نامیم خط میانی خطای خطای، دقیقاً مانند هر نوع واسطه یا درخواست کننده درخواست ، (req, res, next)=> {}
بشر آنچه این را خاص می کند این است که به جای سه پارامتر دارای چهار پارامتر است: (error, req, res, next)=> {}
بشر این دقیقاً مانند هر میانی سفارش سفارش است اما برای رسیدن به آن (در خط لوله یا دنباله میان افزار) باید خطایی را که در آن گرفتاریم عبور کنیم catch (error) { /* */ }
به next
عملکرد. مثال:
function someRequestHandler(req, res, next) {
try {
/* Do something */
} catch (error) {
return next(error);
}
}
بنابراین اکنون ، به جای بازگشت یک پیام کلی که ، "Something went wrong please, try again later.",
حتی بدون اینکه بدانیم چه اشتباهی رخ داده است ، اکنون ما یک مکانیسم فداکار برای تجزیه و بازگرداندن پاسخ خطای مناسب داریم.
امضای میانی دستی خطای ما به این شکل خواهد بود:
/* error-handling middleware */
function errorHandler(error, req, res, next) {
/* */
}
ما از instanceof
اپراتور بررسی اپراتور نمونه ای است که یک شیء نمونه ای از برخی از کلاس ها است. تا کنون ما از آن آگاه هستیم TokenExpiredError
وت JsonWebTokenError
، که نتیجه استفاده از کتابخانه JWT است.
اکنون وقتی مطمئن نیستیم که این خطا چیست ، می توانیم یک پاسخ مناسب را بر اساس نمونه خطا و یک پیام جهانی برگردانیم. ما ممکن است بتوانیم خطا را در یک پرونده ورود به سیستم یا برخی از سرور از راه دور و غیره بنویسیم.
// require TokenExpiredError and JsonWebTokenError from jwt
const { TokenExpiredError, JsonWebTokenError } = require("jsonwebtoken");
...
/* error-handling middleware */
function errorHandler(error, req, res, next) {
if (error instanceof TokenExpiredError) {
return res.status(401).json({
success: false,
message: "Unauthorized: please log in",
});
}
if (error instanceof JsonWebTokenError) {
return res.status(401).json({
success: false,
message: "Unauthorized: please format your auth token",
});
}
// anything else
return res.status(500).json({
success: false,
message: "Internal server error, something went wrong please try again",
// as if the same error would not occur again when the user tries again 😂
});
}
من طرفدار تکیه بر کدهای وضعیت نیستم. من معتقدم API های من “شخص ثالث” هستند و به همین ترتیب این کدهای وضعیت را ارسال می کنند که به طور منحصر به فرد این خطاهای خاص را شناسایی می کنند ، بیش از حد است. شما می خواهید مشتری در هنگام وجود یک API خود را انجام دهد 400
پاسخ خطا یا 500
پاسخ خطا؟ برخی http
مشتریان هنگام بازگشت کد وضعیت ، خطاها را پرتاب می کنند 200
یا 201
بشر بنابراین با نگاهی به خودم به عنوان “شخص ثالث” ، من یک کد خطا ، کد وضعیت یا کلید دیگر را می گیرم و بلافاصله پس از آن کلید حضور می یابد ، پس از آن چیزی پیش آمد. من یک مصرف کرده ام 3 API حزب که در آن بخش موفقیت و خطا وجود دارد.
{
"success": true,
"statusCode": "000001",
"error": {},
"data": {}
}
به هر حال ، همانطور که می دانیم ، ما می توانیم این میان افزار با خطا را در هر نقطه قرار دهیم اما بهتر است زیر نقاط پایانی ثبت شده ما باشد. به عنوان یک تمرین ، کنترل کننده های خود را بپیچید ، تمام دستگیرندگان درخواست شما باید در یک بسته بندی شوند try
وت catch
و خطا را به عملکرد بعدی منتقل کنید. این کار را با خط میانی خطای خطا انجام ندهید. صادقانه بگویم این کار را برای کسانی که به آن احتیاج دارند انجام دهید ، آنهایی که انتظار دارید چیزی اشتباه پیش برود. برخی از کارکردها وجود دارد که من این کار را نمی کنم try and catch
بشر چرا؟ کنترل کننده دارای try
وت catch
بشر
بنابراین همیشه ما به روزرسانی می کنیم به این شکل است:
function SomeFunction(req, res, next) {
try {
/* */
} catch (error) {
return next(error);
}
}
وقتی تمام شد ، این احتمال وجود دارد که ما پاسخ خطا مانند:
{
"success": false,
"message": "Unauthorized: please format your auth token"
}
مورد دیگر خطایی زمانی است که کاربر به نقطه پایانی که وجود ندارد برخورد کند. چگونه می توانیم از این کار برخورد کنیم و آیا خط میانی با خطای ما برای آن حساب می شود؟ نه ، خط میانی خطای خطای آن را به حساب نمی آورد.
خوب ، ایده این است ، ما به یک نقطه پایانی گفتیم ، GET http://localhost:3000/audit
بشر ما هرگز یک نقطه پایانی/مسیر برای حسابرسی تعریف نکردیم. بنابراین در زنجیره ای از میانه و درخواست کنندگان درخواست کننده ، در خط لوله ، هیچ چیز این درخواست را لمس نمی کند ، بنابراین Express آن را کنترل می کند:
lang="en">
charset="utf-8" />
Error
Cannot GET /auditing
Express آن را اداره کرد اما ما می خواهیم برگردیم JSON
نه html
بشر بنابراین ما یک میان افزار نهایی را اضافه می کنیم ، که فقط چیزی را مانند نقطه پایانی که یافت نشد ، باز می گرداند.
باز هم ، این کار را بعد از خط میانی با خطای ما قرار می دهد.
/* not found error-handling middleware */
function notFoundHandler(req, res, next) {
// anything else
return res.status(404).json({
success: false,
message: "Endpoint not found, kindly read our documentation",
});
}
این تابع پس از خطای دست زدن به میانی استفاده می شود.
...
/* global error handling */
app.use(errorHandler);
/* handle cannot [METHOD] some endpoint */
app.use(notFoundHandler);
...
و ما یک پیام JSON دریافت می کنیم.
HTTP/1.1 404 Not Found
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 79
ETag: W/"4f-ZeAuDFW/On8o/z3qFxGFjcV9e4E"
Date: Mon, 03 Mar 2025 09:01:58 GMT
Connection: close
{
"success": false,
"message": "Endpoint not found, kindly read our documentation"
}
منابع