R Academy · درس

مقدمة إلى Plumber وREST

افهم مبادئ REST وعلّم دوال R باستخدام التعليقات التوضيحية كنقاط نهاية API

الدرس 1 من 413 خطوة

مقدمة إلى Plumber وREST درس مجاني في R Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.

ما هي REST API؟

واجهة REST (Representational State Transfer) API هي خدمة ويب تتيح البيانات والعمليات عبر HTTP. ومن مبادئها الأساسية:

  • عديمة الحالة: يحتوي كل طلب على جميع المعلومات اللازمة، ولا توجد جلسة على جانب الخادم.
  • موجّهة نحو الموارد: تمثل نقاط النهاية الموارد (/users، /predictions).
  • أفعال HTTP القياسية: ‏GET (قراءة)، وPOST (إنشاء)، وPUT (تحديث)، وDELETE (إزالة).
  • JSON: تنسيق البيانات القياسي لأجسام الطلبات والاستجابات.
# REST API concepts in HTTP terms:
# GET /api/model/predict?x=5      -> read a prediction
# POST /api/model/train           -> create a new model
# GET /api/data/summary           -> read data summary
# DELETE /api/cache/flush         -> remove cached results

# Plumber maps R functions to these HTTP endpoints
cat('REST: stateless, resource-oriented, JSON responses')

صيغة التعليقات التوضيحية في plumber

يستخدم plumber تعليقات توضيحية خاصة تبدأ بـ #* لتعريف نقاط نهاية API. ضع التعليق التوضيحي مباشرةً فوق دالة R التي تتولى معالجة نقطة النهاية. وترتبط وسيطات الدالة بمعلمات الطلب، بينما تصبح القيمة المرجعة جسم استجابة JSON.

# plumber.R
library(plumber)

#* @get /ping
function() {
  list(status = 'ok', time = Sys.time())
}

#* @get /add
#* @param a:int First number
#* @param b:int Second number
function(a, b) {
  list(result = as.integer(a) + as.integer(b))
}

pr() — إنشاء موجّه Plumber

تقرأ pr('plumber.R') ملف plumber وتنشئ كائن موجّه يسجل جميع نقاط النهاية المشروحة. والموجّه هو الكائن المركزي الذي تهيّئه (بإضافة عوامل التصفية والمسلسِلات وغير ذلك) قبل التشغيل.

library(plumber)

# Create a router from a plumber file
api <- pr('plumber.R')

# Inspect registered routes
print(api$routes)

# Alternatively, define inline without a file:
api <- pr() |>
  pr_get('/ping', function() list(status = 'ok')) |>
  pr_post('/echo', function(req) req$body)

pr_run() — بدء الخادم

تبدأ pr_run(router, host, port) خادم plumber API. ويرتبط افتراضيًا بالعنوان 127.0.0.1:8000. اضبط host = '0.0.0.0' لقبول الاتصالات من أي واجهة شبكة (وهو مطلوب لـ Docker أو للوصول عن بُعد).

library(plumber)

api <- pr('plumber.R')

# Start server on localhost port 8000
# pr_run(api, host = '127.0.0.1', port = 8000)

# For Docker/remote access, bind to all interfaces
# pr_run(api, host = '0.0.0.0', port = 8000)

# View auto-generated Swagger docs in browser
# (automatically available at /docs or /__docs__/ endpoint)
cat('Swagger UI auto-generated at http://localhost:8000/__docs__/')

التعليق التوضيحي @get

يربط التعليق التوضيحي #* @get /path طلب GET بالدالة. وتُمرر معلمات سلسلة الاستعلام (مثل ?name=Alice) تلقائيًا كوسيطات لدالة R. وإذا لم يُحدَّد تعليق توضيحي للتحويل، تصل المعلمات كسلاسل محارف.

# plumber.R

#* Greet a user by name
#* @param name:str The name to greet
#* @get /greet
function(name = 'World') {
  list(
    message = paste('Hello,', name),
    timestamp = format(Sys.time(), '%Y-%m-%d %H:%M:%S')
  )
}
# GET /greet?name=Alice
# -> {"message":"Hello, Alice","timestamp":"2026-01-01 12:00:00"}

التعليق التوضيحي @post

يربط التعليق التوضيحي #* @post /path طلب POST بالدالة. ويمكن الوصول إلى جسم الطلب (وهو عادةً بصيغة JSON) عبر الوسيط الخاص req باستخدام req$body (وهو قائمة محللة عندما يكون جسم الطلب بصيغة JSON). يُستخدم POST للعمليات التي تنشئ موارد أو تطلق عمليات حسابية.

# plumber.R

#* Run a linear model prediction
#* @post /predict
function(req) {
  # req$body is already parsed from JSON
  input_data <- as.data.frame(req$body)

  # Run prediction with a pre-loaded model
  predictions <- predict(trained_model, newdata = input_data)

  list(
    predictions = as.numeric(predictions),
    n           = nrow(input_data)
  )
}

مسلسِل JSON

يحوّل plumber قيم الإرجاع إلى JSON افتراضيًا باستخدام jsonlite. ويجعل التعليق التوضيحي #* @serializer json ذلك صريحًا. ويمكنك تهيئة خيارات التسلسل، مثل التنسيق المحسّن أو التعامل مع القيم الفارغة، بتحديدها كقائمة JSON في التعليق التوضيحي.

# Default: automatic JSON serialization
#* @get /data
function() {
  list(values = 1:5, labels = c('a', 'b', 'c', 'd', 'e'))
}

# Explicit JSON serializer with options
#* @serializer json list(na = 'null', auto_unbox = TRUE)
#* @get /data_explicit
function() {
  list(value = 42, missing = NA)
}
# With auto_unbox=TRUE: {"value":42} not {"value":[42]}

أفعال HTTP — PUT وDELETE وPATCH

يدعم plumber جميع أفعال HTTP القياسية من خلال التعليقات التوضيحية المطابقة:

  • #* @put /path: الاستبدال الكامل لمورد.
  • #* @delete /path: إزالة مورد.
  • #* @patch /path: التحديث الجزئي لمورد.
  • #* @head /path: الرؤوس فقط (من دون جسم).
# plumber.R — CRUD-style endpoints

#* Update a model configuration
#* @put /config/<model_id>
function(model_id, req) {
  config <- req$body
  save_config(model_id, config)
  list(updated = model_id, config = config)
}

#* Remove cached results
#* @delete /cache/<key>
function(key) {
  cache_env <- globalenv()$cache
  rm(list = key, envir = cache_env)
  list(deleted = key)
}

معلمات المسار

تُعرَّف معلمات المسار باستخدام الأقواس الزاوية في المسار: /user/. يستخرج plumber القيمة من عنوان URL ويمررها كوسيط للدالة بالاسم نفسه. وتختلف هذه المعلمات عن معلمات الاستعلام (التي تظهر بعد ?).

# plumber.R

#* Get stats for a specific dataset
#* @param dataset_id:str The dataset identifier
#* @get /datasets/<dataset_id>/stats
function(dataset_id) {
  if (!dataset_id %in% available_datasets()) {
    stop(paste('Dataset not found:', dataset_id))
  }
  ds <- load_dataset(dataset_id)
  list(
    id    = dataset_id,
    rows  = nrow(ds),
    cols  = ncol(ds),
    names = names(ds)
  )
}

معالجة الأخطاء

عندما تُصدر دالة R خطأً، يلتقطه plumber ويعيد استجابة HTTP برمز 500، مع رسالة الخطأ بصيغة JSON. وفي واجهات API الموجهة للمستخدمين، أعد رموز حالة HTTP المناسبة صراحةً باستخدام res$status وstop() لأخطاء التحقق.

# plumber.R

#* Divide two numbers safely
#* @get /divide
function(a, b, res) {
  a <- suppressWarnings(as.numeric(a))
  b <- suppressWarnings(as.numeric(b))

  if (is.na(a) || is.na(b)) {
    res$status <- 400  # Bad Request
    return(list(error = 'Both a and b must be numeric'))
  }
  if (b == 0) {
    res$status <- 422  # Unprocessable Entity
    return(list(error = 'Division by zero is not allowed'))
  }
  list(result = a / b)
}

توثيق Swagger المُنشأ تلقائيًا

ينشئ plumber تلقائيًا توثيق Swagger تفاعليًا من تعليقاتك التوضيحية. انتقل إلى /__docs__/ أثناء تشغيل الخادم لعرض جميع نقاط النهاية ومعلماتها وتجربتها في المتصفح. استخدم #* @tag لتجميع نقاط النهاية منطقيًا.

# plumber.R with Swagger metadata

#* @apiTitle My ML Prediction API
#* @apiDescription Serves predictions from trained R models
#* @apiVersion 1.0.0

#* @tag model
#* @get /health
function() list(status = 'healthy')

#* Predict house price
#* @tag prediction
#* @param sqft:dbl Square footage
#* @param bedrooms:int Number of bedrooms
#* @get /predict
function(sqft = 1000, bedrooms = 3) {
  pred <- predict(price_model, data.frame(sqft = as.numeric(sqft),
                                          bedrooms = as.integer(bedrooms)))
  list(predicted_price = round(as.numeric(pred), 2))
}

تحقق سريع

في plumber، ما الفرق بين معلمة الاستعلام (مثل /greet?name=Alice) ومعلمة المسار (مثل /user/42)؟

مراجعة plumber وREST

أهم النقاط من درس مقدمة إلى plumber وREST:

  • REST: عديمة الحالة، وموجهة نحو الموارد، وتستخدم أفعال HTTP القياسية، وتعيد JSON.
  • يربط plumber دوال R بنقاط النهاية باستخدام التعليقات التوضيحية #* فوق الدوال.
  • تنشئ pr('file.R') موجّهًا؛ وتبدأ pr_run(api, host, port) الخادم.
  • يتولى #* @get /path معالجة GET؛ ويتولى #* @post /path معالجة POST.
  • معلمات المسار: /user/؛ ومعلمات الاستعلام: /search?term=foo.
  • أعد قوائم مسماة — إذ يحوّلها plumber إلى JSON تلقائيًا.
  • يُنشأ Swagger UI تلقائيًا على /__docs__/ من تعليقاتك التوضيحية.
# Complete minimal plumber API
library(plumber)

#* @apiTitle Simple Prediction API

#* Health check
#* @get /health
function() list(status = 'ok')

#* Predict mpg from weight
#* @param wt:dbl Car weight (1000 lbs)
#* @get /predict
function(wt = 3.0) {
  pred <- predict(lm(mpg ~ wt, data = mtcars),
                  newdata = data.frame(wt = as.numeric(wt)))
  list(wt = as.numeric(wt), predicted_mpg = round(pred, 2))
}

# Run:
# api <- pr('plumber.R')
# pr_run(api, port = 8000)
البدء مجانًا

تعلم R مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
43
الدروس
159

الأسئلة الشائعة

هل درس «مقدمة إلى Plumber وREST» مجاني؟

نعم — نص درس «مقدمة إلى Plumber وREST» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.

ماذا ستتعلم في «مقدمة إلى Plumber وREST»؟

افهم مبادئ REST وعلّم دوال R باستخدام التعليقات التوضيحية كنقاط نهاية API تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟

لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «مقدمة إلى Plumber وREST»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟

نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. مقدمة إلى Plumber وREST
  2. إنشاء نقاط نهاية GET وPOST
  3. المصادقة وأمان API
  4. نشر Plumber APIs في بيئة الإنتاج
← العودة إلى R Academy