Example #1
0
QByteArray HttpHeaders::getAsFirstParameter(const QByteArray &key) const
{
	HttpHeaderParameters p = getAsParameters(key);
	if(p.isEmpty())
		return QByteArray();

	return p[0].first;
}
Example #2
0
Instruct Instruct::fromResponse(const HttpResponseData &response, bool *ok, QString *errorMessage)
{
	HoldMode holdMode = NoHold;
	QList<Channel> channels;
	int timeout = -1;
	QList<QByteArray> exposeHeaders;
	QByteArray keepAliveData;
	int keepAliveTimeout = -1;
	QHash<QString, QString> meta;
	HttpResponseData newResponse;

	if(response.headers.contains("Grip-Hold"))
	{
		QByteArray gripHoldStr = response.headers.get("Grip-Hold");
		if(gripHoldStr == "response")
		{
			holdMode = ResponseHold;
		}
		else if(gripHoldStr == "stream")
		{
			holdMode = StreamHold;
		}
		else
		{
			setError(ok, errorMessage, "Grip-Hold must be set to either 'response' or 'stream'");
			return Instruct();
		}
	}

	QList<HttpHeaderParameters> gripChannels = response.headers.getAllAsParameters("Grip-Channel");
	foreach(const HttpHeaderParameters &gripChannel, gripChannels)
	{
		if(gripChannel.isEmpty())
		{
			setError(ok, errorMessage, "failed to parse Grip-Channel");
			return Instruct();
		}

		Channel c;
		c.name = QString::fromUtf8(gripChannel[0].first);
		QByteArray param = gripChannel.get("prev-id");
		if(!param.isNull())
			c.prevId = QString::fromUtf8(param);

		for(int n = 1; n < gripChannel.count(); ++n)
		{
			const HttpHeaderParameter &param = gripChannel[n];
			if(param.first == "filter")
				c.filters += QString::fromUtf8(param.second);
		}

		channels += c;
	}

	if(response.headers.contains("Grip-Timeout"))
	{
		bool x;
		timeout = response.headers.get("Grip-Timeout").toInt(&x);
		if(!x)
		{
			setError(ok, errorMessage, "failed to parse Grip-Timeout");
			return Instruct();
		}

		if(timeout < 0)
		{
			setError(ok, errorMessage, "Grip-Timeout has invalid value");
			return Instruct();
		}
	}

	exposeHeaders = response.headers.getAll("Grip-Expose-Headers");

	HttpHeaderParameters keepAliveParams = response.headers.getAsParameters("Grip-Keep-Alive");
	if(!keepAliveParams.isEmpty())
	{
		QByteArray val = keepAliveParams[0].first;
		if(val.isEmpty())
		{
			setError(ok, errorMessage, "Grip-Keep-Alive cannot be empty");
			return Instruct();
		}

		if(keepAliveParams.contains("timeout"))
		{
			bool x;
			keepAliveTimeout = keepAliveParams.get("timeout").toInt(&x);
			if(!x)
			{
				setError(ok, errorMessage, "failed to parse Grip-Keep-Alive timeout value");
				return Instruct();
			}

			if(keepAliveTimeout < 0)
			{
				setError(ok, errorMessage, "Grip-Keep-Alive timeout has invalid value");
				return Instruct();
			}
		}
		else
		{
			keepAliveTimeout = DEFAULT_RESPONSE_TIMEOUT;
		}

		QByteArray format = keepAliveParams.get("format");
		if(format.isEmpty() || format == "raw")
		{
			keepAliveData = val;
		}
		else if(format == "cstring")
		{
			keepAliveData = unescape(val);
			if(keepAliveData.isNull())
			{
				setError(ok, errorMessage, "failed to parse Grip-Keep-Alive cstring format");
				return Instruct();
			}
		}
		else if(format == "base64")
		{
			keepAliveData = QByteArray::fromBase64(val);
		}
		else
		{
			setError(ok, errorMessage, QString("no such Grip-Keep-Alive format '%1'").arg(QString::fromUtf8(format)));
			return Instruct();
		}
	}

	QList<HttpHeaderParameters> metaParams = response.headers.getAllAsParameters("Grip-Set-Meta", HttpHeaders::ParseAllParameters);
	foreach(const HttpHeaderParameters &metaParam, metaParams)
	{
		if(metaParam.isEmpty())
		{
			setError(ok, errorMessage, "Grip-Set-Meta cannot be empty");
			return Instruct();
		}

		QString key = QString::fromUtf8(metaParam[0].first);
		QString val = QString::fromUtf8(metaParam[0].second);

		meta[key] = val;
	}

	newResponse = response;

	QByteArray statusHeader = response.headers.get("Grip-Status");
	if(!statusHeader.isEmpty())
	{
		QByteArray codeStr;
		QByteArray reason;

		int at = statusHeader.indexOf(' ');
		if(at != -1)
		{
			codeStr = statusHeader.mid(0, at);
			reason = statusHeader.mid(at + 1);
		}
		else
		{
			codeStr = statusHeader;
		}

		bool _ok;
		newResponse.code = codeStr.toInt(&_ok);
		if(!_ok || newResponse.code < 0 || newResponse.code > 999)
		{
			setError(ok, errorMessage, "Grip-Status contains invalid status code");
			return Instruct();
		}

		newResponse.reason = reason;
	}

	QUrl nextLink;
	int nextLinkTimeout = -1;
	foreach(const HttpHeaderParameters &params, response.headers.getAllAsParameters("Grip-Link"))
	{
		if(params.count() >= 2 && params.get("rel") == "next")
		{
			QByteArray linkParam = params[0].first;
			if(linkParam.length() <= 2 || linkParam[0] != '<' || linkParam[linkParam.length() - 1] != '>')
			{
				setError(ok, errorMessage, "failed to parse Grip-Link value");
				return Instruct();
			}

			nextLink = QUrl::fromEncoded(linkParam.mid(1, linkParam.length() - 2));
			if(!nextLink.isValid())
			{
				setError(ok, errorMessage, "Grip-Link contains invalid link");
				return Instruct();
			}

			if(params.contains("timeout"))
			{
				bool x;
				nextLinkTimeout = params.get("timeout").toInt(&x);
				if(!x)
				{
					setError(ok, errorMessage, "failed to parse Grip-Link timeout value");
					return Instruct();
				}

				if(nextLinkTimeout < 0)
				{
					setError(ok, errorMessage, "Grip-Link timeout has invalid value");
					return Instruct();
				}
			}
			else
			{
				nextLinkTimeout = DEFAULT_NEXTLINK_TIMEOUT;
			}
		}
	}

	newResponse.headers.clear();
	foreach(const HttpHeader &h, response.headers)
	{
		// strip out grip headers
		if(qstrnicmp(h.first.data(), "Grip-", 5) == 0)
			continue;

		if(!exposeHeaders.isEmpty())
		{
			bool found = false;
			foreach(const QByteArray &e, exposeHeaders)
			{
				if(qstricmp(e.data(), h.first.data()) == 0)
				{
					found = true;
					break;
				}
			}

			if(!found)
				continue;
		}

		newResponse.headers += HttpHeader(h.first, h.second);
	}