HTML5 Server-Sent-Events not working on Firefox6+ browsers? - events

This is my ASP.NET for server sent events.
Response.ContentType = "text/event-stream";
Response.CacheControl = "no-cache";
//repeat loop
while (true) {
int LastEventId = Request.Headers.Get("Last-Event-ID") != null ?
Int32.Parse(Request.Headers.Get("Last-Event-ID")) : -1;
int MessageCount = UserManager.GetMessageCount(UserManager.GetUserDetails(Page.User.Identity.Name).UserId);
if (LastEventId != MessageCount)
{
Response.Write(string.Format("retry: 5000\nid: {0}\ndata: {0}\n\n", MessageCount));
Response.Flush();
}
else
{
Response.Write(string.Format("retry: 5000\nid: {0}\ndata: \n\n", MessageCount));
Response.Flush();
}
if (Response.IsClientConnected == false)
{
break;
}
Response.Close();
System.Threading.Thread.Sleep(5000);
}
Firefox browser does not reconnect after two times. The same code is working on Google Chrome. Can any one help me out with this?

Try to remove spaces after colons. Seems that Firefox parser is very sensitive to spaces and newlines. Try to change your code like this:
Response.Write(string.Format("retry:5000\nid:{0}\ndata:{0}\n\n", MessageCount));
Also defining a charset may help in some browsers:
Response.ContentType = "text/event-stream;charset=UTF-8";
Hope this helps.

Related

QHttpMultiPart generates different boundary

When I try to upload files by QHttpMultiPart, there appears a problem. I use the CommonsMultipartResolver.isMultipart() to validate the request, and it returns false.
So I capture frame by Wireshark, and I found an interesting thing: the boundaries in the frame are all different.
Here is my client code
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart zipPart;
zipPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/zip"));
zipPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\""));
QFile *file = new QFile(pakPath);
file->open(QIODevice::ReadOnly);
zipPart.setBodyDevice(file);
multiPart->append(zipPart);
QNetworkRequest *request = new QNetworkRequest(QUrl(url));
manager->put(*request, multiPart);
And the server code
CommonsMultipartResolver(request.getSession().getServletContext());
if( multipartResolver.isMultipart(request) ) { // here return false
...
I have two questions:
Q1: Is the different boundary make itself be an abnormal in CommonsMultipartResolver?
Q2: Is Different boundary normal or Qt make mistake?
I have a same problem too , my boundary supposed whitout "" ,
I find the source code about QHttpMultiPart class , I found that qt has force set "" by hand . so whatever we set , it will always with "".
qt QHttpMultiPart source code
<pre><code>QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
{
// copy the request, we probably need to add some headers
QNetworkRequest newRequest(request);
// add Content-Type header if not there already
if (!request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
QByteArray contentType;
contentType.reserve(34 + multiPart->d_func()->boundary.count());
contentType += "multipart/";
switch (multiPart->d_func()->contentType) {
case QHttpMultiPart::RelatedType:
contentType += "related";
break;
case QHttpMultiPart::FormDataType:
contentType += "form-data";
break;
case QHttpMultiPart::AlternativeType:
contentType += "alternative";
break;
default:
contentType += "mixed";
break;
}
// putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
contentType += "; boundary=\"" + multiPart->d_func()->boundary + '"';
newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType));
}
// add MIME-Version header if not there already (we must include the header
// if the message conforms to RFC 2045, see section 4 of that RFC)
QByteArray mimeHeader("MIME-Version");
if (!request.hasRawHeader(mimeHeader))
newRequest.setRawHeader(mimeHeader, QByteArray("1.0"));
QIODevice *device = multiPart->d_func()->device;
if (!device->isReadable()) {
if (!device->isOpen()) {
if (!device->open(QIODevice::ReadOnly))
qWarning("could not open device for reading");
} else {
qWarning("device is not readable");
}
}
return newRequest;
}
</code></pre>
I tried to inherit QHttpMultiPart and rewrite the QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart) function , but it seems too bother to do.
finally , I found a simple way to solve that , it just need to reset boundary paramter agian , that before you post data. it worked. here is my code
<pre><code>
void PeddingBizUI::ossUploadPicture_post(PolicyInfo policy, QString pathName)
{
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart keyPart;
QString fileName = getFileNameFromPath(pathName);
keyPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-
data; name=\"key\""));
QByteArray ba = QByteArray(QString(policy.dir +
fileName).toStdString().data());
qDebug()<<ba;
keyPart.setBody(ba);
QHttpPart policyPart;
policyPart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"policy\""));
policyPart.setBody(policy.policy.toStdString().data());
QHttpPart SignaturePart;
SignaturePart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"Signature\""));
SignaturePart.setBody(policy.signature.toStdString().data());
QHttpPart OSSAccessKeyIdPart;
OSSAccessKeyIdPart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"OSSAccessKeyId\""));
OSSAccessKeyIdPart.setBody(policy.accessId.toStdString().data());
QHttpPart success_action_statusPart;
success_action_statusPart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"success_action_status\""));
success_action_statusPart.setBody(QByteArray::number(200));
QHttpPart aclPart;
aclPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-
data; name=\"x-oss-object-acl\""));
aclPart.setBody("public-read");
QHttpPart imagePart;
QString str = QString("form-data; name=\"file\";
filename=\"%1\"").arg(fileName);
qDebug()<<fileName;
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(str));
//不可调换header的先后顺序否则导致
imagePart.setHeader(QNetworkRequest::ContentTypeHeader,
QVariant("image/jpeg")); //请求失败, 提示body data not well formed 失
败
QFile *fileOpen = new QFile(pathName);
fileOpen->open(QIODevice::ReadOnly);
imagePart.setBodyDevice(fileOpen);
fileOpen->setParent(multiPart); // we cannot delete the file now, so delete it
with the multiPart
multiPart->append(keyPart);
multiPart->append(policyPart);
multiPart->append(SignaturePart);
multiPart->append(OSSAccessKeyIdPart);
multiPart->append(success_action_statusPart);
//multiPart->append(aclPart);
multiPart->append(imagePart);
quint32 random[6];
QRandomGenerator::global()->fillRange(random);
QByteArray boundary = "--boundary_zyl_"
+ QByteArray::fromRawData(reinterpret_cast<char *>(random),
sizeof(random)).toBase64();
QUrl url(policy.host);
// QUrl url("http://arithmetic-oss.oss-cn-shenzhen.aliyuncs.com");
QNetworkRequest request(url);
QByteArray contentType;
contentType += "multipart/";
contentType += "form-data";
contentType += "; boundary=";
contentType += boundary;
multiPart->setBoundary(boundary);
request.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
QNetworkReply *reply = m_netUtils.m_manager->post(request, multiPart);
connect(reply, &QNetworkReply::finished, this, [this, multiPart](){
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
qDebug()<<"ossUploadPicture_post response";
onOssUploadPictureResponse(reply);
multiPart->setParent(reply); //内存泄露
reply->deleteLater();
});
// delete the multiPart with the reply
}</code></pre>
and then problem solved.

LinqToTwitter User Stream memory leak

I'm having an issue with LinqToTwitter 4.1 where having a user stream open will eventually cause the programs memory usage to balloon out of control. This does not occur when the program starts running but only after some time, normally after a day or two.
Using the ANTS Memory Profiler I find this reference chain preventing System.Byte[] from being collected. The full profiler results can be downloaded here.
Code:
private async Task<Streaming> TwitterSteam(string trackHashTags, string twitterUserIds)
{
var stream = (from strm in TwitterCtx.Streaming.WithCancellation(CloseStreamSource.Token)
where strm.Type == StreamingType.Filter &&
strm.Track == trackHashTags
&& strm.Follow == (string.IsNullOrEmpty(twitterUserIds) ? "41553192" : twitterUserIds)
select strm).StartAsync(async strm =>
{
string message = string.IsNullOrEmpty(strm.Content) ? "Keep-Alive" : strm.Content;
if (message == "Keep-Alive")
{
IsRunning = true;
}
else
{
JsonData data = JsonMapper.ToObject(message);
Status tweet = new Status(data);
LogClient.LogInfo("Received Tweet: " + tweet.Text, null, LogType.Info, null);
ConvertToMessage(tweet);
IsRunning = true;
}
}).Result.SingleOrDefault();
return stream;
}
Can anyone provide insight as to why this is occurring and how I can prevent it?

could not complete operation due to error c00ce514

I have this code as an excel downloader. After the excel has been generated.
But I'm having an error. As stated in the question Title.
The error occurs at the line:
var strResponeText = XMLHttpRequestObject.responseText;
var strUrl = "POSSellThroughReportExcelOpener.aspx?getstatus=1&DateFrom=" + hdnDateFrom.value + "&DateTo=" + hdnDateTo.value + "&customer_id=" + hdnCustomerID.value + "&intdisplayby=" + hdnDisplayBy.value + "&monthorweek=" + hdnMonthOrWeek.value;
if (XMLHttpRequestObject) {
XMLHttpRequestObject.open("POST", strUrl);
XMLHttpRequestObject.onreadystatechange = function () {
if ((XMLHttpRequestObject.readyState == 4) && (XMLHttpRequestObject.status == 200)) {
var hdnRedirectUrl = document.getElementById("hdnRedirectUrl");
var strResponeText = XMLHttpRequestObject.responseText;
var intResponse = new Number(strResponeText);
var spanCallBackStatus = document.getElementById("spanCallBackStatus");
var trClose = document.getElementById("trClose");
if (!isNaN(intResponse)) {
if (intResponse == 1) {
spanCallBackStatus.innerHTML = "Excel Report has been generated."
trClose.style.display = "";
Init();
window.location.href = hdnRedirectUrl.value;
}
else {
GetStatus();
}
}
else {
spanCallBackStatus.innerHTML = strResponeText;
}
}
}
XMLHttpRequestObject.send(null);
}
Any help is greatly appreciated.
Many thanks.
UPDATE - FEB 20,2014 3:55PM (PHILIPPINE TIME)
Hi Guys,
I have found the cause of the error, it is because the content-type is called two times. During Page_Load event and at last line of the Generate Excel function which is not supposed to be. That is why the current content-type after the page loads has been replaced after the generate excel function. Hehe my bad I guess.
Anyway thanks for all the help, advice and useful links.
Good day to all. :D
Internet Explorer can't handle binary responses to AJAX requests like XMLHttpRequestObject, as discussed in this question. You need to handle the response in some other way, depending on what you need to do with it.

IE & Ajax / XPath

I've read countless threads and tried implementing many different suggestions, but haven't had any luck.
first:
function ajaxRequest() {
try {
var request = new XMLHttpRequest();
}
catch(e1) {
try {
var request = new ActiveXObject("Msxml2.HTMLHTTP");
}
catch(e2) {
try {
var request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e3) {
var request = false;
}
}
}
return request;
}
It looks like IE is successfully using XMLHttpRequest. As far as I can tell, it's loading the XML fine, but Xpath is another story:
function XMLPath(doc, path) {
try {
return doc.evaluate(path, doc, null, XPathResult.STRING_TYPE, null).stringValue;
} catch (e) {
try {
doc.setProperty("SelectionLanguage", "XPath");
return doc.selectNodes(path);
}
catch(e2) {
alert(e2);
}
}
}
Basically, what must I change in my catch statement to make it work with IE? What's also interesting is that it never alerts an e2 error, meaning it's not actually throwing an error. Totally confused.
Thanks.
Try return doc.selectSingleNode(path).text; for IE, that is the closest you can get for accessing the string value of the node found by your path.

Why don't InfoCards work in IE8?

What changed in IE8 that makes detecting InfoCard Selector support in javascript stop working unless IE8 is put in Compatibility Mode?
And more to the point, what is the new JavaScript code to detect the presence of InfoCard support?
Here is the script that worked up through IE7, including FireFox with a plug-in in some cases:
function AreCardsSupported() {
var IEVer = -1;
if (navigator.appName == 'Microsoft Internet Explorer') {
if (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) {
IEVer = parseFloat(RegExp.$1);
}
}
// Look for IE 7+.
if (IEVer >= 7) {
var embed = document.createElement("object");
embed.setAttribute("type", "application/x-informationcard");
return "" + embed.issuerPolicy != "undefined" && embed.isInstalled;
}
// not IE (any version)
if (IEVer < 0 && navigator.mimeTypes && navigator.mimeTypes.length) {
// check to see if there is a mimeType handler.
x = navigator.mimeTypes['application/x-informationcard'];
if (x && x.enabledPlugin) {
return true;
}
// check for the IdentitySelector event handler is there.
if (document.addEventListener) {
var event = document.createEvent("Events");
event.initEvent("IdentitySelectorAvailable", true, true);
top.dispatchEvent(event);
if (top.IdentitySelectorAvailable == true) {
return true;
}
}
}
return false;
}
I got an answer out of band from the IE8 team:
Change
embed.setAttribute("type", "application/x-informationcard");
to
embed.type = "application/x-informationcard";

Resources