В этом посте освещается попытка взглянуть на необработанный формат данных, отправленных в теле запроса POST, и способы их анализа. Существуют такие пакеты, как body-parser для Express, которые делают это за нас, поэтому этот пост предназначен только для учебных целей. Я не предлагаю использовать это решение в производстве.

При отправке почтовых запросов на сервер через отправку HTML-формы данные, отправляемые на серверную часть, обычно настраиваются с одним из следующих типов мультимедиа: application / x-www-form-urlencoded, multipart / данные формы или текст / простой. В этом примере я смотрю на application / x-www-form-urlencoded.

Создание нашего сервера

Давайте настроим его, используя приведенный ниже фрагмент:

const http = require('http');
const server = http.createServer((req, res) => {
    res.end(`
        <!doctype html>
        <html>
        <body>
            <form action="/" method="post">
                <input type="text" name="fname" /><br />
                <input type="number" name="age" /><br />
                <input type="file" name="photo" /><br />
                <button>Save</button>
            </form>
        </body>
        </html>
    `);
});
server.listen(3000);

Это должно открыть страницу по адресу http: // localhost: 3000 с веб-формой:

Заполнение полей и нажатие кнопки «Сохранить» отправит результаты по корневому пути, содержащему поля данных, как и ожидалось. При этом будет использоваться тип носителя по умолчанию application / x-www-form-urlencoded. Это означает, что он создаст строку запроса, используя имена полей в качестве ключей и их данные в качестве значений.

Захват POSTed данных

Чтобы настроить сцену для захвата этих данных, мы должны сначала проверить, что это запрос POST:

const http = require('http');
const server = http.createServer((req, res) => {
    if (req.method === 'POST') {
        // Handle post info...
    }
    else {
      res.end(`
        <!doctype html>
        <html>
        <body>
            <form action="/" method="post">
                <input type="text" name="fname" /><br />
                <input type="number" name="age" /><br />
                <input type="file" name="photo" /><br />
                <button>Save</button>
            </form>
        </body>
        </html>
      `);
    }
});
server.listen(3000);

Учитывая, что запрос, отправленный на серверную часть, является Читаемым потоком, EventEmitter API используется как средство чтения данных. этот поток (нам не нужно импортировать здесь модуль 'событий', поскольку объект запроса расширяет EventEmitter):

...
if (req.method === 'POST') {
    let body = '';
    req.on('data', chunk => {
        body += chunk.toString(); // convert Buffer to string
    });
    req.on('end', () => {
        console.log(body);
        res.end('ok');
    });
}
...

Заполнение формы и нажатие кнопки «Сохранить» приведет к выходу этой информации на консоль:

fname=Jermaine&age=29&photo=jermaine-photo.png

Каждое поле в форме разделяется символом амперсанда (&), а ключ и значения разделяются символом равенства.

Анализ данных

Чтобы упростить доступ к каждой паре ключ / значение, мы будем использовать встроенный в Node модуль querystring для преобразования данных в объект:

// At the top of the file
const { parse } = require('querystring');
...
...
if (req.method === 'POST') {
    let body = '';
    req.on('data', chunk => {
        body += chunk.toString();
    });
    req.on('end', () => {
        console.log(
            parse(body)
        );
        res.end('ok');
    });
}
...

Результат будет ниже:

{
    fname: 'Jermaine',
    age: '29',
    photo: 'jermaine-photo.jpg'
}

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

function collectRequestData(request, callback) {
    const FORM_URLENCODED = 'application/x-www-form-urlencoded';
    if(request.headers['content-type'] === FORM_URLENCODED) {
        let body = '';
        request.on('data', chunk => {
            body += chunk.toString();
        });
        request.on('end', () => {
            callback(parse(body));
        });
    }
    else {
        callback(null);
    }
}

Мы будем использовать нашу функцию так:

...
if(req.method === 'POST') {
    collectRequestData(req, result => {
        console.log(result);
        res.end(`Parsed data belonging to ${result.fname}`);
    });
}
...

Заполните форму, и при отправке должно появиться сообщение ниже:

Ниже представлено полное решение:

Ограничения

Вы бы заметили, что при загрузке файла серверной части отправляется только имя файла, а не сам файл. Это ограничение типа носителя application / x-www-form-urlencoded. Использование multipart / form-data отправит необработанный файл вместе с его метаданными. Возможно, в одном из следующих постов мы рассмотрим, как это можно сделать! А пока вот как обрабатывать тело запроса POST в Dart без использования фреймворка.

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

Интересно, что я веду канал YouTube, обучающий подписчиков созданию полнофункциональных приложений с использованием языка Dart и его экосистемы. Подпишитесь сегодня и присоединяйтесь ко мне в этом путешествии.

Как всегда, мы ждем ваших отзывов. Спасибо заранее.

Дальнейшее чтение