Как сервер должен реализовать связывание промежуточного программного обеспечения? - PullRequest
0 голосов
/ 27 марта 2020

Я изо всех сил пытаюсь понять логику c за модулем ExpressJS, в частности я сосредоточен на реализации цепочки промежуточного программного обеспечения.

Моя цель здесь чтобы понять, как можно реализовать логи c сервера, который прослушивает запросы и, как только он поступит, пропускает пакет запроса через массив функций, каждая из которых:

  1. должна быть в состоянии изменить пакет для следующего промежуточного программного обеспечения
  2. должен иметь возможность отправить ответ назад, но это не должно помешать другим промежуточным программам также ответить, поэтому в конце цепочки должен быть только один ответ (я полагаю)
  3. должен получить доступ к некоторой функции для вызова, чтобы запустить промежуточное ПО next в цепочке, но без нужно передать ему параметры запроса и ответа (например, просто вызвать " next () ")

Примечание к пункту 1

Я представляю, что с такими языками, как javascript р Можно обойти объект, используя такие понятия, как замыкание, но я хотел бы понять его независимым от языка способом и использовать функции javascript, только если он предоставляет умные способы простой обработки, в противном случае я напишу логи c как я использовал любой другой язык.

Итак, мои большие вопросы:

  1. Как должна быть реализована обработка запросов?
  2. Как разрешить каждое промежуточное ПО? изменить пакет?
  3. Как передать обновленный пакет следующему промежуточному программному обеспечению?
  4. Как реализовать функцию "next" для передачи каждому промежуточному программному обеспечению?

Спасибо

Ответы [ 2 ]

0 голосов
/ 27 марта 2020

Вот небольшой рабочий сервер, который поддерживает промежуточное ПО и маршруты GET. Он использует аналогичное соглашение о вызовах для обработчиков маршрутов, как Express (req, res, next), но имеет намного, намного, намного меньше возможностей, чем Express. Но, надеюсь, вы сможете увидеть, как функция диспетчеризации циклически перебирает маршруты, переходя к следующему маршруту, только если предыдущий обработчик вызывает next().

Вы можете запустить этот код, определить маршруты и поиграть с ним ( хотя это определенно базовые основы c):

const http = require('http');

function dispatch(req, res, array, index, cb) {
    console.log(req.method, req.url, array, index);
    if (array && array.length > index) {
        let item = array[index];
        if (!item.path || item.path.toLowerCase() === req.url.toLowerCase()) {
            item.fn(req, res, function() {
                // previous route called next(), so we advance to the next item in the array
                ++index;
                dispatch(req, res, array, index, cb);
            });
            return;
        }
    }
    cb();
}

const server = http.createServer((req, res) => {
    // incoming request here, initiate calling the middleware
    dispatch(req, res, server.middleware, 0, function() {
        if (req.method === "GET") {
            dispatch(req, res, server.gets, 0, function() {
                // done with gets here, apparently didn't send a response
                res.statusCode = 404;
                res.end();
            })
        } else {
            // ... fill in code for other methods here
            res.statusCode = 404;
            res.end();
        }
    });
});

// server route implementation
// save arrays for each type of route handler
// upon a request, run all the middleware requests, then advance
// to the routes for the right type of request and see if any of them
// match the URL.  If so, run them.
server.middleware = [];
server.gets = [];
server.posts = [];

server.use = function(fn) {
    server.middleware.push({path: "", fn: fn});
}

server.get = function(path, fn) {
    server.gets.push({path, fn});
}


// route definitions
server.use((req, res, next) => {
    console.log(req.url);
    req.myCustom = "hi";
    next();
});

server.use((req, res, next) => {
    console.log(req.myCustom);
    next();
});

server.get("/", (req, res, next) => {
    res.write("Hello World");
    res.end();
});

server.listen(80);
0 голосов
/ 27 марта 2020

В общем, именно так можно вызвать цепочку промежуточного программного обеспечения со следующей функцией.

function myMiddleware(req, res, next) {
   // do something with req or res
   next();
}

const mws = [
  myMiddleware,
  anotherMiddleware
];

/**
 * Calls a chain of middlewares.
 *
 * mws is an array of middlewares
 */
function callMwChain(req, res, mws) {
   if (mws.length === 0) {
     // We're done here
     return;
   }

   /**
    * Take the first middleware
    */
   const firstMw = mws[0];


   /**
    * Call it, and give it a next function that continues the chain
    */
   firstMw(req, res, () => {
      callMwChain(req, res, mws.slice(1));
   });

}

Я написал это как рекурсивную функцию, но ее также можно переписать как стек. Это проще, хотя.

Express промежуточные программы имеют много бонусных магий c, поэтому их реализация будет более сложной, но в целом это работает.

Примечание что в поле зрения нет события-l oop.

...