Allow response header value to contain a colon

HTTP response header field values are allowed to contain separators
(which includes the colon) as long as they appear within quotes
(http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2). This
commit enables `Browser#response_headers` to handle a field value that
contains a colon followed by a space (i.e., ": ") without breaking.
This commit is contained in:
Ryan Winograd 2015-02-08 17:09:55 -06:00 committed by Joe Ferris
parent e8cc0fa382
commit c0c9d701ef
5 changed files with 28 additions and 7 deletions

View File

@ -71,7 +71,7 @@ module Capybara::Webkit
end end
def response_headers def response_headers
Hash[command("Headers").split("\n").map { |header| header.split(": ") }] JSON.parse(command("Headers"))
end end
def current_url def current_url

View File

@ -2974,6 +2974,24 @@ CACHE MANIFEST
end end
end end
context "response header contains colon" do
let(:driver) do
driver_for_app do
get "/" do
headers "Content-Disposition" => 'filename="File: name.txt"'
end
end
end
it "sets the response header" do
visit("/")
expect(
driver.response_headers["Content-Disposition"]
).to eq 'filename="File: name.txt"'
end
end
def driver_url(driver, path) def driver_url(driver, path)
URI.parse(driver.current_url).merge(path).to_s URI.parse(driver.current_url).merge(path).to_s
end end

View File

@ -1,11 +1,14 @@
#include "Headers.h" #include "Headers.h"
#include "WebPage.h" #include "WebPage.h"
#include "WebPageManager.h" #include "WebPageManager.h"
#include "JsonSerializer.h"
Headers::Headers(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) { Headers::Headers(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
} }
void Headers::start() { void Headers::start() {
finish(true, page()->pageHeaders().join("\n")); JsonSerializer serializer;
QByteArray json = serializer.serialize(page()->pageHeaders());
finish(true, json);
} }

View File

@ -83,9 +83,9 @@ void WebPage::setFrameProperties(QWebFrame *frame, QUrl &requestedUrl, NetworkRe
if (frame->requestedUrl() == requestedUrl) { if (frame->requestedUrl() == requestedUrl) {
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
frame->setProperty("statusCode", statusCode); frame->setProperty("statusCode", statusCode);
QStringList headers; QVariantMap headers;
foreach(QNetworkReply::RawHeaderPair header, reply->rawHeaderPairs()) foreach(QNetworkReply::RawHeaderPair header, reply->rawHeaderPairs())
headers << header.first+": "+header.second; headers[header.first] = QString(header.second);
frame->setProperty("headers", headers); frame->setProperty("headers", headers);
frame->setProperty("body", reply->data()); frame->setProperty("body", reply->data());
QVariant contentMimeType = reply->header(QNetworkRequest::ContentTypeHeader); QVariant contentMimeType = reply->header(QNetworkRequest::ContentTypeHeader);
@ -359,8 +359,8 @@ int WebPage::getLastStatus() {
return currentFrame()->property("statusCode").toInt(); return currentFrame()->property("statusCode").toInt();
} }
QStringList WebPage::pageHeaders() { QVariantMap WebPage::pageHeaders() {
return currentFrame()->property("headers").toStringList(); return currentFrame()->property("headers").toMap();
} }
QByteArray WebPage::body() { QByteArray WebPage::body() {

View File

@ -47,7 +47,7 @@ class WebPage : public QWebPage {
bool matchesWindowSelector(QString); bool matchesWindowSelector(QString);
void setFocus(); void setFocus();
void unsupportedContentFinishedReply(QNetworkReply *reply); void unsupportedContentFinishedReply(QNetworkReply *reply);
QStringList pageHeaders(); QVariantMap pageHeaders();
QByteArray body(); QByteArray body();
QString contentType(); QString contentType();
void mouseEvent(QEvent::Type type, const QPoint &position, Qt::MouseButton button); void mouseEvent(QEvent::Type type, const QPoint &position, Qt::MouseButton button);