QtWebEngine: Implement custom HTTP headers
This commit is contained in:
parent
5a54699863
commit
44d1056e54
@ -711,16 +711,12 @@ Valid values:
|
||||
|
||||
Default: +pass:[true]+
|
||||
|
||||
This setting is only available with the QtWebKit backend.
|
||||
|
||||
[[network-accept-language]]
|
||||
=== accept-language
|
||||
Value to send in the `accept-language` header.
|
||||
|
||||
Default: +pass:[en-US,en]+
|
||||
|
||||
This setting is only available with the QtWebKit backend.
|
||||
|
||||
[[network-referer-header]]
|
||||
=== referer-header
|
||||
Send the Referer header
|
||||
@ -804,8 +800,6 @@ Set custom headers for qutebrowser HTTP requests.
|
||||
|
||||
Default: empty
|
||||
|
||||
This setting is only available with the QtWebKit backend.
|
||||
|
||||
== completion
|
||||
Options related to completion and command history.
|
||||
|
||||
|
@ -18,3 +18,24 @@
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Various utilities shared between webpage/webview subclasses."""
|
||||
|
||||
from qutebrowser.config import config
|
||||
|
||||
|
||||
def custom_headers():
|
||||
"""Get the combined custom headers."""
|
||||
headers = {}
|
||||
dnt = b'1' if config.get('network', 'do-not-track') else b'0'
|
||||
headers[b'DNT'] = dnt
|
||||
headers[b'X-Do-Not-Track'] = dnt
|
||||
|
||||
custom_headers = config.get('network', 'custom-headers')
|
||||
if custom_headers is not None:
|
||||
for header, value in custom_headers.items():
|
||||
headers[header.encode('ascii')] = value.encode('ascii')
|
||||
|
||||
accept_language = config.get('network', 'accept-language')
|
||||
if accept_language is not None:
|
||||
headers[b'Accept-Language'] = accept_language.encode('ascii')
|
||||
|
||||
return sorted(headers.items())
|
||||
|
@ -22,6 +22,7 @@
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
|
||||
|
||||
from qutebrowser.browser import shared
|
||||
from qutebrowser.utils import utils, log
|
||||
|
||||
|
||||
@ -59,3 +60,6 @@ class RequestInterceptor(QWebEngineUrlRequestInterceptor):
|
||||
log.webview.info("Request to {} blocked by host blocker.".format(
|
||||
info.requestUrl().host()))
|
||||
info.block(True)
|
||||
|
||||
for header, value in shared.custom_headers():
|
||||
info.setHttpHeader(header, value)
|
||||
|
@ -31,6 +31,7 @@ from PyQt5.QtNetwork import (QNetworkAccessManager, QNetworkReply, QSslError,
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import (message, log, usertypes, utils, objreg, qtutils,
|
||||
urlutils, debug)
|
||||
from qutebrowser.browser import shared
|
||||
from qutebrowser.browser.webkit.network import qutescheme, networkreply
|
||||
from qutebrowser.browser.webkit.network import filescheme
|
||||
|
||||
@ -449,6 +450,9 @@ class NetworkManager(QNetworkAccessManager):
|
||||
if result is not None:
|
||||
return result
|
||||
|
||||
for header, value in shared.custom_headers():
|
||||
req.setRawHeader(header, value)
|
||||
|
||||
host_blocker = objreg.get('host-blocker')
|
||||
if (op == QNetworkAccessManager.GetOperation and
|
||||
host_blocker.is_blocked(req.url())):
|
||||
@ -458,20 +462,6 @@ class NetworkManager(QNetworkAccessManager):
|
||||
req, HOSTBLOCK_ERROR_STRING, QNetworkReply.ContentAccessDenied,
|
||||
self)
|
||||
|
||||
if config.get('network', 'do-not-track'):
|
||||
dnt = '1'.encode('ascii')
|
||||
else:
|
||||
dnt = '0'.encode('ascii')
|
||||
req.setRawHeader('DNT'.encode('ascii'), dnt)
|
||||
req.setRawHeader('X-Do-Not-Track'.encode('ascii'), dnt)
|
||||
|
||||
# Load custom headers
|
||||
custom_headers = config.get('network', 'custom-headers')
|
||||
|
||||
if custom_headers is not None:
|
||||
for header, value in custom_headers.items():
|
||||
req.setRawHeader(header.encode('ascii'), value.encode('ascii'))
|
||||
|
||||
# There are some scenarios where we can't figure out current_url:
|
||||
# - There's a generic NetworkManager, e.g. for downloads
|
||||
# - The download was in a tab which is now closed.
|
||||
@ -490,10 +480,6 @@ class NetworkManager(QNetworkAccessManager):
|
||||
|
||||
self.set_referer(req, current_url)
|
||||
|
||||
accept_language = config.get('network', 'accept-language')
|
||||
if accept_language is not None:
|
||||
req.setRawHeader('Accept-Language'.encode('ascii'),
|
||||
accept_language.encode('ascii'))
|
||||
if PYQT_VERSION < 0x050301:
|
||||
# WORKAROUND (remove this when we bump the requirements to 5.3.1)
|
||||
#
|
||||
|
@ -388,13 +388,11 @@ def data(readonly=False):
|
||||
|
||||
('network', sect.KeyValue(
|
||||
('do-not-track',
|
||||
SettingValue(typ.Bool(), 'true',
|
||||
backends=[usertypes.Backend.QtWebKit]),
|
||||
SettingValue(typ.Bool(), 'true'),
|
||||
"Value to send in the `DNT` header."),
|
||||
|
||||
('accept-language',
|
||||
SettingValue(typ.String(none_ok=True), 'en-US,en',
|
||||
backends=[usertypes.Backend.QtWebKit]),
|
||||
SettingValue(typ.String(none_ok=True), 'en-US,en'),
|
||||
"Value to send in the `accept-language` header."),
|
||||
|
||||
('referer-header',
|
||||
@ -437,8 +435,7 @@ def data(readonly=False):
|
||||
"Whether to try to pre-fetch DNS entries to speed up browsing."),
|
||||
|
||||
('custom-headers',
|
||||
SettingValue(typ.HeaderDict(none_ok=True), '',
|
||||
backends=[usertypes.Backend.QtWebKit]),
|
||||
SettingValue(typ.HeaderDict(none_ok=True), ''),
|
||||
"Set custom headers for qutebrowser HTTP requests."),
|
||||
|
||||
readonly=readonly
|
||||
|
@ -74,6 +74,8 @@ PERFECT_FILES = [
|
||||
|
||||
('tests/unit/browser/test_signalfilter.py',
|
||||
'qutebrowser/browser/signalfilter.py'),
|
||||
('tests/unit/browser/test_shared.py',
|
||||
'qutebrowser/browser/shared.py'),
|
||||
# ('tests/unit/browser/test_tab.py',
|
||||
# 'qutebrowser/browser/tab.py'),
|
||||
|
||||
|
@ -394,12 +394,28 @@ Feature: Various utility commands.
|
||||
|
||||
## Custom headers
|
||||
|
||||
@qtwebengine_todo: Custom headers are not implemented yet
|
||||
Scenario: Setting a custom header
|
||||
When I set network -> custom-headers to {"X-Qute-Test": "testvalue"}
|
||||
And I open headers
|
||||
Then the header X-Qute-Test should be set to testvalue
|
||||
|
||||
Scenario: DNT header
|
||||
When I set network -> do-not-track to true
|
||||
And I open headers
|
||||
Then the header Dnt should be set to 1
|
||||
And the header X-Do-Not-Track should be set to 1
|
||||
|
||||
Scenario: DNT header (off)
|
||||
When I set network -> do-not-track to false
|
||||
And I open headers
|
||||
Then the header Dnt should be set to 0
|
||||
And the header X-Do-Not-Track should be set to 0
|
||||
|
||||
Scenario: Accept-Language header
|
||||
When I set network -> accept-language to en,de
|
||||
And I open headers
|
||||
Then the header Accept-Language should be set to en,de
|
||||
|
||||
## :messages
|
||||
|
||||
@qtwebengine_todo: qute:log is not implemented yet
|
||||
|
51
tests/unit/browser/test_shared.py
Normal file
51
tests/unit/browser/test_shared.py
Normal file
@ -0,0 +1,51 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2016 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
|
||||
from qutebrowser.browser import shared
|
||||
|
||||
|
||||
@pytest.mark.parametrize('dnt, accept_language, custom_headers, expected', [
|
||||
# DNT
|
||||
(True, None, {}, {b'DNT': b'1', b'X-Do-Not-Track': b'1'}),
|
||||
(False, None, {}, {b'DNT': b'0', b'X-Do-Not-Track': b'0'}),
|
||||
# Accept-Language
|
||||
(False, 'de, en', {}, {b'DNT': b'0', b'X-Do-Not-Track': b'0',
|
||||
b'Accept-Language': b'de, en'}),
|
||||
# Custom headers
|
||||
(False, None, {'X-Qute': 'yes'}, {b'DNT': b'0', b'X-Do-Not-Track': b'0',
|
||||
b'X-Qute': b'yes'}),
|
||||
# Mixed
|
||||
(False, 'de, en', {'X-Qute': 'yes'}, {b'DNT': b'0',
|
||||
b'X-Do-Not-Track': b'0',
|
||||
b'Accept-Language': b'de, en',
|
||||
b'X-Qute': b'yes'}),
|
||||
])
|
||||
def test_custom_headers(config_stub, dnt, accept_language, custom_headers,
|
||||
expected):
|
||||
config_stub.data = {
|
||||
'network': {
|
||||
'do-not-track': dnt,
|
||||
'accept-language': accept_language,
|
||||
'custom-headers': custom_headers,
|
||||
}
|
||||
}
|
||||
expected_items = sorted(expected.items())
|
||||
assert shared.custom_headers() == expected_items
|
Loading…
Reference in New Issue
Block a user