1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/sogou-workflow

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
tutorial-01-wget.md 7.3 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 01.03.2025 10:20 552780a

Создание первого задания: wget

Пример кода

tutorial-01-wget.cc

О wget

Программа считывает HTTP/HTTPS URL с stdin, скачивает страницу и выводит её содержимое в stdout, а также печатает запрос и ответ HTTP заголовков в stderr. Для простоты программа завершается при нажатии Ctrl+C, но гарантируется полное освобождение всех ресурсов.

Создание и запуск HTTP задачи

WFHttpTask *task = WFTaskFactory::create_http_task(url, REDIRECT_MAX, RETRY_MAX, wget_callback);
protocol::HttpRequest *req = task->get_req();
req->add_header_pair("Accept", "*/*");
req->add_header_pair("User-Agent", "Wget/1.14 (gnu-linux)");
req->add_header_pair("Connection", "close");
task->start();
pause();

Метод WFTaskFactory::create_http_task() создает HTTP задачу; в файле WFTaskFactory.h определен следующий прототип:

WFHttpTask *create_http_task(const std::string& url,
                             int redirect_max, int retry_max,
                             http_callback_t callback);

Первые несколько параметров не требуют особого объяснения, http_callback_t — это callback для HTTP задачи, определенный следующим образом:

using http_callback_t = std::function<void (WFHttpTask *)>;

Конкретнее говоря, это функция с одним параметром типа Task, которая не имеет возвращаемого значения. Этот callback может принимать NULL, что указывает на отсутствие необходимости использования callback. Все наши задачи используют этот стиль callback. Необходимо отметить, что все методы фабрик никогда не возвращают ошибки, поэтому не стоит беспокоиться о том, что task будет пустым указателем, даже если URL некорректен. Все ошибки обрабатываются в callback. Метод task->get_req() получает запрос задачи, по умолчанию используется метод GET, HTTP/1.1, долгосрочное соединение. Фреймворк автоматически добавляет request_uri, Host и другие заголовки. Фреймворк автоматически добавляет заголовки Content-Length или Connection перед отправкой, если это требуется. Пользователи могут использовать метод add_header_pair() для добавления своих заголовков. Дополнительные интерфейсы для HTTP сообщений можно найти в файле HttpMessage.h. Метод task->start() запускает задачу, он является асинхронным и никогда не возвращает ошибки. После этого callback обязательно будет вызван. Из-за асинхронной работы после start() уже нельзя использовать указатель task. Чтобы сделать пример как можно более простым, после start() вызывается pause() для предотвращения завершения программы, пользователь должен завершить программу через Ctrl-C.

Обработка результатов HTTP-запроса

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

void wget_callback(WFHttpTask *task)
{
    protocol::HttpRequest *req = task->get_req();
    protocol::HttpResponse *resp = task->get_resp();
    int state = task->get_state();
    int error = task->get_error();

    // обработка состояний ошибок
    ...

    std::string name;
    std::string value;
    // вывод запроса в stderr
    fprintf(stderr, "%s %s %s\r\n", req->get_method(), req->get_http_version(), req->get_request_uri());
    protocol::HttpHeaderCursor req_cursor(req);
    while (req_cursor.next(name, value))
        fprintf(stderr, "%s: %s\r\n", name.c_str(), value.c_str());
    fprintf(stderr, "\r\n");

    // вывод заголовков ответа в stderr
    ...

    // вывод тела ответа в stdout
    const void *body;
    size_t body_len;
    resp->get_parsed_body(&body, &body_len); // всегда успешен.
    fwrite(body, 1, body_len, stdout);
    fflush(stdout);
}

В этом callback'е task представляет собой задачу, созданную через фабрику. Метод task->get_state() и task->get_error() позволяют получить состояние выполнения задачи и код ошибки соответственно. Мы пропустим часть обработки ошибок. Метод task->get_resp() получает ответ задачи, который отличается немного от запроса, так как они являются производными от HttpMessage. Затем используется объект HttpHeaderCursor для сканирования заголовков запроса и ответа. В файле HttpUtil.h можно найти определение Cursor.

class HttpHeaderCursor
{
public:
    HttpHeaderCursor(const HttpMessage *message);
    ...
    void rewind();
    ...
    bool next(std::string& name, std::string& value);
    bool find(const std::string& name, std::string& value);
    ...
};

Надеюсь, использование этого cursor'a не вызовет никаких вопросов. Следующая строка resp->get_parsed_body() получает тело ответа HTTP. Этот вызов гарантированно возвращает true при успешном выполнении задачи, body указывает на область данных. Этот вызов возвращает первоначальное тело HTTP, не декодируя chunk-кодировку. Для декодирования chunk-кодировки можно использовать HttpChunkCursor из файла HttpUtil.h. Кроме того, следует отметить, что метод find() изменяет внутренние указатели курсора, то есть после использования find() для дальнейшей итерации по заголовкам необходимо вернуться к началу курсора с помощью метода rewind().

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/sogou-workflow.git
git@api.gitlife.ru:oschina-mirror/sogou-workflow.git
oschina-mirror
sogou-workflow
sogou-workflow
master