QtWebEngine Fetch API терпит неудачу с пользовательской схемой

#qt #qml #fetch #chromium #qtwebengine

#qt #qml #выборка #chromium #qtwebengine

Вопрос:

Я пытаюсь создать пользовательскую схему для QtWebEngineView с помощью QWebEngineUrlSchemeHandler для обслуживания веб-страницы с локального диска. Страница использует Fetch API для запроса некоторых файлов json.

Вот реализация для моей пользовательской схемы

appschemehandler.cpp

 AppSchemeHandler::AppSchemeHandler(QObject *parent):
    QWebEngineUrlSchemeHandler(parent),
    m_scheme(QWebEngineUrlScheme("app"))
{
    m_scheme.setFlags(
        QWebEngineUrlScheme::SecureScheme |
        QWebEngineUrlScheme::LocalAccessAllowed |
        QWebEngineUrlScheme::ViewSourceAllowed |
        QWebEngineUrlScheme::ContentSecurityPolicyIgnored |
        QWebEngineUrlScheme::CorsEnabled
    );
    QWebEngineUrlScheme::registerScheme(m_scheme);
}

void AppSchemeHandler::install()
{
    QWebEngineProfile::defaultProfile()->installUrlSchemeHandler("app", this);
}

void AppSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job)
{
    ...
}

  

main.cpp

 int main(int argc, char *argv[])
{
    AppSchemeHandler appSchemeHandler(nullptr);

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    appSchemeHandler.install();


    QQmlApplicationEngine engine;

    const QUrl url(QStringLiteral("qrc:/main.qml"));

    QObject::connect(amp;engine, amp;QQmlApplicationEngine::objectCreated,
                     amp;app, [url](QObject *obj, const QUrl amp;objUrl) {
        if (!obj amp;amp; url == objUrl)
            QCoreApplication::exit(-1);

    }, Qt::QueuedConnection);


    engine.load(url);

    return app.exec();
}
  

main.qml

 Window {
    id: browser

    visible: true
    width: 800
    height: 600

    WebEngineView {
        id: webengine

        anchors.fill: parent
        url: 'app://my-app'
    }
}
  

index.html

 <!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Lets Fetch!</title>
</head>
<body>
    <h1>Lets Fetch!</h1>
    <script>
        fetch("/myFile.json").then(res => console.log(res.json()));
    </script>
</body>
</html>
  

Все работает так, как должно, пока веб-страница не попытается fetch() . Это то, что я получаю в консоли chromium.
Fetch API cannot load app://my-app/myFile.json. URL scheme "app" is not supported.

Я провел быстрый тест с помощью Electron, который предоставляет protocol.registerSchemesAsPrivileged() , и проблем с использованием Fetch API нет. Итак, затем я проверил аргументы процесса electron и нашел --fetch-schemes=app . Я думаю, что это не аргумент Chromium (Blink?), Поскольку изменений нет, даже если я передаю его в свое приложение Qt напрямую или через QTWEBENGINE_CHROMIUM_FLAGS переменную среды.

Каков способ Qt добавления пользовательских схем выборки?

Комментарии:

1. поделитесь .qml…

2. @eyllanesc Я обновил свой вопрос. Это очень просто, поэтому я не думаю, что это слишком актуально при работе с пользовательскими схемами.

3. Верьте или нет, иногда, когда это кажется простым и ошибки не могут быть допущены, это является причиной проблемы (не обязательно в данном случае).

4. Не могу с этим поспорить. Был там миллион раз. : D

Ответ №1:

Это не правильный ответ на ваш вопрос (который, по-видимому, является известной ошибкой), а возможный обходной путь:

Похоже fetch() , что он отлично работает с запросами, которые начинаются с URL-адреса http, а затем перенаправляются на пользовательскую схему с помощью a QWebEngineUrlRequestInterceptor . Итак, для вашего примера выполните fetch("http://my-app/myFile.json") в JavaScript, а затем перенаправьте это app://my-app/myFile.json с помощью перехватчика. К сожалению, это означает изменение кода JavaScript, но это может быть лучше, чем ничего.

Это код Python, который я использовал, который должен быть простым для переноса на C :

 class Interceptor(QtWebEngineCore.QWebEngineUrlRequestInterceptor):
    def interceptRequest(self, info):
        url = info.requestUrl()
        if url.scheme() != 'http' or url.host() != 'my-app':
            return

        url.setScheme('app')
        info.redirect(url)
  

Затем этот перехватчик устанавливается на QWebEngineProfile с profile.setUrlRequestInterceptor(interceptor) помощью .

Ответ №2:

Исправление было интегрировано в ветку разработки и будет доступно в Qt 6.6. Затем вы можете добавить QWebEngineUrlScheme::FetchApiAllowed к флагам, и это должно сработать.

 m_scheme.setFlags(
        QWebEngineUrlScheme::SecureScheme |
        QWebEngineUrlScheme::LocalAccessAllowed |
        QWebEngineUrlScheme::ViewSourceAllowed |
        QWebEngineUrlScheme::ContentSecurityPolicyIgnored |
        QWebEngineUrlScheme::CorsEnabled |
        QWebEngineUrlScheme::FetchApiAllowed
    );