While reading about Server-Sent Events from this page, I got confused about the timing of events. Basically, the example shown has a PHP script sending the system time to the web page:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>
While the page receives and renders it:
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("demo_sse.php");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
My confusion is that the server seems to be sending messages every 3-4 seconds:
The server time is: Tue, 20 Sep 2016 11:55:12 -0400
The server time is: Tue, 20 Sep 2016 11:55:16 -0400
The server time is: Tue, 20 Sep 2016 11:55:20 -0400
The server time is: Tue, 20 Sep 2016 11:55:23 -0400
The server time is: Tue, 20 Sep 2016 11:55:28 -0400
The server time is: Tue, 20 Sep 2016 11:55:32 -0400
The server time is: Tue, 20 Sep 2016 11:55:35 -0400
The server time is: Tue, 20 Sep 2016 11:55:39 -0400
The server time is: Tue, 20 Sep 2016 11:55:43 -0400
The server time is: Tue, 20 Sep 2016 11:55:46 -0400
The server time is: Tue, 20 Sep 2016 11:55:50 -0400
The server time is: Tue, 20 Sep 2016 11:55:53 -0400
The server time is: Tue, 20 Sep 2016 11:55:57 -0400
The server time is: Tue, 20 Sep 2016 11:56:01 -0400
The server time is: Tue, 20 Sep 2016 11:56:04 -0400
The server time is: Tue, 20 Sep 2016 11:56:08 -0400
The server time is: Tue, 20 Sep 2016 11:56:12 -0400
The server time is: Tue, 20 Sep 2016 11:56:15 -0400
However, I don't see this delay either at the server end or at the client end. Is it the network lag between the website's server and my browser? Or is it something else?
Default retry is 3 seconds as shown on http://www.html5rocks.com/en/tutorials/eventsource/basics/
Check out the "Controlling the Reconnection-timeout section" on that link.
You may customize it by sending a line retry:100
to enforce just 100ms retry time interval.
Related
We wanted to leverage an existing API Gateway and alter the destination of some errors in an application not hosted in AWS from an RDS to a CloudWatch log group and stream but when testing it I get a SerializationException every time
The model of the data coming into the gateway is
{
"Message":"foo",
"StackTrace":"bar",
"Category": "example"
"CustomData":{"foo":"bar","fee","fum"},
"Timestamp": 1564043651175
}
The timestamp was added as it is required to insert a CloudWatch log as shown [here]: https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html
The following is some of the CloudFormation yaml that defines the API Gateway which is making the requests
Uri:
Fn::Join:
- ''
- - 'arn:aws:apigateway:'
- !Ref AWS::Region
- ":logs:action/PutLogEvents"
RequestTemplates:
application/json: !Sub |
#set($inputRoot = $input.path('$'))
#set($context.requestOverride.header['X-Amz-Target'] = "Logs_20140328.PutLogEvents")
#set($context.requestOverride.header['Content-Type'] = "application/x-amz-json-1.1")
{
"logGroupName": "${Prefix}-err-group"
"logStreamName": "${Prefix}-app-errors"
"logEvents": [
{
"message": "message: $inputRoot.Message, stackTrace: $inputRoot.StackTrace, category: $inputRoot.Category, customData: $inputRoot.CustomData",
"timestamp": "$inputRoot.Timestamp"
}
]
}
The API method deploys successfully and when testing it in the console using the Method Test and the model above I get the following output from the test
Thu Jul 25 08:14:24 UTC 2019 : Starting execution for request: 364e53c8-aeb4-11e9-91f6-ab8c0812e717
Thu Jul 25 08:14:24 UTC 2019 : HTTP Method: POST, Resource Path: /
Thu Jul 25 08:14:24 UTC 2019 : Method request path: {}
Thu Jul 25 08:14:24 UTC 2019 : Method request query string: {}
Thu Jul 25 08:14:24 UTC 2019 : Method request headers: {}
Thu Jul 25 08:14:24 UTC 2019 : Method request body before transformations: {
"Message": "Example Message",
"StackTrace": "Example StackTrace",
"Category": "Category1",
"CustomData": {"GUID": "17e332e5-9d03-4e0d-83b1-874f62cb33bb","One": "1","Version": "28.1.1.0","ErrorId": "1212"},
"Timestamp": 1564040369451
}
Thu Jul 25 08:14:24 UTC 2019 : Request validation succeeded for content type application/json
Thu Jul 25 08:14:24 UTC 2019 : Request parameter overrides:
Add X-Amz-Target: Logs_20140328.PutLogEvents
Add Content-Type: application/x-amz-json-1.1
Thu Jul 25 08:14:24 UTC 2019 : Endpoint request URI: https://logs.eu-west-2.amazonaws.com/?Action=PutLogEvents
Thu Jul 25 08:14:24 UTC 2019 : Endpoint request headers: {Authorization=<Redacted>, X-Amz-Date=20190725T081424Z, x-amzn-apigateway-api-id=<Redacted>, Accept=application/json, User-Agent=AmazonAPIGateway_<Redacted>, X-Amz-Security-Token=<Redacted>[TRUNCATED]
Thu Jul 25 08:14:24 UTC 2019 : Endpoint request body after transformations: {
"logGroupName": "test-err-group"
"logStreamName": "test-app-errors"
"logEvents": [
{
"message": "message: Example Message, stackTrace: Example StackTrace, category, Category1, customData: {GUID=17e332e5-9d03-4e0d-83b1-874f62cb33bb,One=1,Version=28.1.1.0,ErrorId=1212}",
"timestamp": "1564040369451"
}
]
}
Thu Jul 25 08:14:24 UTC 2019 : Sending request to https://logs.eu-west-2.amazonaws.com/?Action=PutLogEvents
Thu Jul 25 08:14:24 UTC 2019 : Received response. Status: 400, Integration latency: 7 ms
Thu Jul 25 08:14:24 UTC 2019 : Endpoint response headers: {x-amzn-RequestId=3655f4fb-aeb4-11e9-8498-591aad10a10c, Content-Type=application/x-amz-json-1.1, Content-Length=35, Date=Thu, 25 Jul 2019 08:14:23 GMT, Connection=close}
Thu Jul 25 08:14:24 UTC 2019 : Endpoint response body before transformations: {"__type":"SerializationException"}
Thu Jul 25 08:14:24 UTC 2019 : Method response body after transformations: {"__type":"SerializationException"}
Thu Jul 25 08:14:24 UTC 2019 : Method response headers: {X-Amzn-Trace-Id=Root=1-5d3964e0-291c033c3040ef301afc81c5, Access-Control-Allow-Origin=*, Content-Type=application/json}
Thu Jul 25 08:14:24 UTC 2019 : Successfully completed execution
Thu Jul 25 08:14:24 UTC 2019 : Method completed with status: 200
This still occurs when I replace the more complex json request body with a simple string. I found [this post]: Getting SerializationException while trying to PutLogEvents on cloudwatch using golang when someone had the same exception but it was due to a problem with their GoLang rather than going through API
Turns out I was missing 2 commas after logGroupName and logStreamName. Blinded by looking at it for too long
I already asked on answers.unity3d but as there is no response I'll ask on SO too..
I'm not able to retrieve the http status of a response on the WWW object on Windows Phone 8 and Windows RT 8.1 (while it's ok on IOS/Android).
www.responseHeader["STATUS"] does not exists and the hidden field _responseHeaderString does not contain as first line
HTTP/1.1 200 OK
responseHeaderString :
Server: nginx
Date: Wed, 21 Oct 2015 07:44:36 GMT
Last-Modified: Mon, 07 Sep 2015 11:43:46 GMT
Connection: keep-alive
Expires: Fri, 20 Nov 2015 07:44:36 GMT
Cache-Control: max-age=2592000
Cache-Control: public
responseHeader :
{
"SERVER" : "nginx"
"DATE" : "Wed, 21 Oct 2015 07:44:36 GMT"
"LAST-MODIFIED": "Mon, 07 Sep 2015 11:43:46 GMT"
"CONNECTION" : "keep-alive"
"EXPIRES" : "Fri, 20 Nov 2015 07:44:36 GMT"
"CACHE-CONTROL": "public"
}
Sample code to reproduce : (tested on an empty new project)
WWW www = new WWW("http://www.google.com");
yield return www;
Debug.Log("Google Status : " + www.responseHeaders.ContainsKey("STATUS")); // False
Debug.Log(www.text); // <doctype ...
Debug.Log(www.responseHeaders["STATUS"]); // KeyError
Am I missing something or is there someone that can confirm this as a bug ?
Edit:
Still not able to retrieve the http status with the latest 5.3
Your network server is probably responding with a different (unexpected) response to each device. For various reasons such as the user agent string, which could lead the WWW class to not get the STATUS.
Firstly, I would install a proxy so you can see exactly what the phone sends and what the server raw response is. Either Charles Proxy (mac/windows) or Fiddler (windows) are great.
Here is the actual code that Unity WWW class is using to generate status:
if (num++ == 0 && text.StartsWith("HTTP"))
{
dictionary["STATUS"] = text;
}
Ref: https://github.com/MattRix/UnityDecompiled/blob/master/UnityEngine/UnityEngine/WWW.cs#L483
From the proxy it should be clear what is happening. If not, post the request and response here (as raw).
Try reading the www.error before looking for the STATUS header.
// Construct the response object
string error = www.error;
if (error == null) {
if (www.responseHeaders.ContainsKey("STATUS")) {
string [] status=www.responseHeaders["STATUS"].Split(' ');
if (status.Length>2 && status[2] != "OK") {
error = www.responseHeaders["STATUS"];
}
}
}
I have sails.js application.
When I add record to my MySQL database there is field createdAt - type dateTime.
In MySql console createdAt value looks like Wed Mar 25 2015 00:00:00 GMT+0100
When I try to get this data as JSON using sails.js controller I get
2015-03-24T23:00:00.000Z - which is 1 hour elier?
My system time zone is GMT +1.
How can I get the same time in db and JSON rsponse?
'list': function (req, res, next) {
Tests.find().exec(function (err, tests) {
if (err) res.json({ error: 'DB error' }, 500);
if (tests) {
_.each(tests, function (data) {
console.log("Date: " + JSON.stringify(data.createdAt)+" "+data.createdAt);
})
res.status(200).json(tests);
}
});
And console output is:
Date: "2015-03-10T14:28:51.000Z" Tue Mar 10 2015 15:28:51 GMT+0100
Date: "2015-03-16T10:25:34.000Z" Mon Mar 16 2015 11:25:34 GMT+0100
Date: "2015-03-16T11:27:23.000Z" Mon Mar 16 2015 12:27:23 GMT+0100
Date: "2015-03-16T11:33:39.000Z" Mon Mar 16 2015 12:33:39 GMT+0100
Date: "2015-03-16T11:34:41.000Z" Mon Mar 16 2015 12:34:41 GMT+0100
Date: "2015-03-16T12:13:21.000Z" Mon Mar 16 2015 13:13:21 GMT+0100
Date: "2015-03-16T13:54:03.000Z" Mon Mar 16 2015 14:54:03 GMT+0100
It all happends while converting to JSON - still dont know how to fix it.
JSON.stringify(data.createdAt) is equal to data.createdAt.toJSON() and it is equal to data.createdAt.toISOString()
data.createdAt is equal to data.createdAt.toString()
the time value is equal; toString() returns it according your time zone, while toISOString() in GMT.
to get the Date from JSON string use conversion function as 2nd parameter of JSON.parse(), you can use the regexp rx = /([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\.([0-9]{3})Z/ to check the date ISO format and then convert it to date d = new Date(str)
What is the type of createdAt in your Mysql database? Is it Date? If yes try setting it to varchar. And if you need to manipulate it or format it you can use moment js.
The last few hours, I have tried to figure out, why the following image is not cached in the browser, after it is requested the first time:
http://runrpg.net/assets/images/screenshots/placeit_outdoor_wide.jpg
I understand that the correct headers have to be set, and currently the response header looks like this:
HTTP/1.1 200 OK
Date: Sat, 04 Jan 2014 16:35:53 GMT
Server: Apache/2.4.4 (Unix) OpenSSL/1.0.1e PHP/5.5.3 mod_perl/2.0.8-dev
Perl/v5.16.3
Last-Modified: Sat, 30 Nov 2013 01:37:52 GMT
ETag: "1dac5-4ec5afebf3c00-gzip"
Accept-Ranges: bytes
Cache-Control: max-age=2592000
Expires: Mon, 03 Feb 2014 16:35:53 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: image/jpeg
As you can see, the "Expires" header is set to "Mon, 03 Feb 2014 16:35:53 GMT" and I also included a "Cache-Control: max-age=2592000".
Can you help me and tell me what I am missing?
Your help would be very much appreciated.
Thanks!
This is most likely due to your server not validating ETags correctly. While cache validation through the Last-Modified header works perfectly:
$ HEAD -H "If-Modified-Since: Sat, 30 Nov 2013 01:37:52 GMT" http://runrpg.net/assets/images/screenshots/placeit_outdoor_wide.jpg
304 Not Modified
Cache-Control: max-age=290304000, public
Connection: close
Date: Sat, 04 Jan 2014 19:01:30 GMT
ETag: "1dac5-4ec5afebf3c00"
Server: Apache/2.4.4 (Unix) OpenSSL/1.0.1e PHP/5.5.3 mod_perl/2.0.8-dev Perl/v5.16.3
Expires: Thu, 09 Jan 2014 19:01:30 GMT
Client-Date: Sat, 04 Jan 2014 19:01:30 GMT
Client-Peer: 80.70.3.110:80
Client-Response-Num: 1
The same cannot be said with ETags:
$ HEAD -H 'If-None-Match: "1dac5-4ec5afebf3c00-gzip"' http://runrpg.net/assets/images/screenshots/placeit_outdoor_wide.jpg
200 OK
Cache-Control: max-age=290304000, public
Connection: close
Date: Sat, 04 Jan 2014 19:02:24 GMT
Accept-Ranges: bytes
ETag: "1dac5-4ec5afebf3c00"
Server: Apache/2.4.4 (Unix) OpenSSL/1.0.1e PHP/5.5.3 mod_perl/2.0.8-dev Perl/v5.16.3
Vary: Accept-Encoding
Content-Length: 121541
Content-Type: image/jpeg
Expires: Thu, 09 Jan 2014 19:02:24 GMT
Last-Modified: Sat, 30 Nov 2013 01:37:52 GMT
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: origin, x-requested-with, content-type, X-Titanium-Id
Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Origin: http://127.0.0.1:8020
Client-Date: Sat, 04 Jan 2014 19:02:24 GMT
Client-Peer: 80.70.3.110:80
Client-Response-Num: 1
Bottom line: The problem is your server, not any clients. This seems to be a known issue with Apache 2.4.x. A quick solution to this is by switching ETags off:
FileETag None
I have an array with lots of items with same names like
CloudObserverCMSStub edited
CloudObserverCMSStub edited
CloudObserverCMSStub created
CloudObserverCMSStub2 edited
CloudObserverCMSStub2 edited
CloudObserverCMSStub2 created
and different related to names dates for each item in such format
Wed, 17 Mar 2010 22:32:09 GMT
Wed, 17 Mar 2010 22:32:07 GMT
Wed, 17 Mar 2010 22:32:02 GMT
Wed, 17 Mar 2010 22:31:02 GMT
Wed, 17 Mar 2010 21:32:02 GMT
Wed, 15 Mar 2009 22:32:02 GMT
I want to sort them so that I get only the latest ones in such format (with no such stuff like edited or created)
CloudObserverCMSStub | Wed, 17 Mar 2010 22:32:09 GMT
CloudObserverCMSStub2 | Wed, 17 Mar 2010 22:31:02 GMT
So I want a new array of 2 items from for example 6 how to do such thing?
You create an object, store the common names as the keys, and use dates as values. Then you can compare the dates and replace it if the date is more recent. Eg:
var obj:Object;
for(var element in array) // I honestly forget AS3 syntax.
{
if(obj[element.name] == null)
{
obj[element.name] = element;
}
else
{
if(obj[element.name].date > element.date)
{
obj[element.name] = element;
}
}
}
Then just enumerate all the elements in obj.