I have a page that has some heavy content and takes around 1.5 minutes to fully load. I have added the retrieve data on scroll functionality where am calling an ajax request when the user scrolls to retrieve data.
I have wrapped the data retrieval behavior to a function handleEventsLoad() and called this function on load trying to cover the case where the user scrolls before the page fully loads reaching the end:
$(document).ready(function()
{
$(window).scroll(function()
{
handleEventsLoad();
});
handleEventsLoad();
});
The ajax request is called properly, though, the first time this request is called I cannot read any session data at PHP level in $_SESSION knowing that the session is being set on page load and if I print it in the HTML I can see its value.
After the page fully loads the first time and I refresh the page, the same request is called but this time I can read the session data properly and the auto load on scroll functions as expected (the difference here is that all the data have been cached and the pages takes 7 sec to load).
Does the loading process have anything to do with reading the session at ajax call?
Here is a sample of the ajax :
function handleEventsLoad()
{
if($('#sidebar').length > 0
&& $(window).scrollTop() >= $('#sidebar').offset().top + $('#sidebar').outerHeight() - window.innerHeight)
{
$.ajax({
url: "ajaxUrl.php",
type: 'GET',
dataType: 'json',
data: {/* passing some data */},
success:function(data)
{
// some code here
},
error: function(xhr, status, error)
{
var err = eval("(" + xhr.responseText + ")");
console.log(err.Message);
}
});
}
}
ajaxUrl.php
<?php
session_start();
print_r($_SESSION);
return;
?>
UPDATE
Please find below the difference between HTTP requests between the first and second ajax calls:
Request:
First Call:
Connection: keep-alive
Second Call:
Cookie: _ga=GA1.2.1253088293.1457289524; _gat=1; PHPSESSID=79c38493322374f1bc19541f4c538b02
Connection: keep-alive
Cache-Control: max-age=0
Response:
First Call:
Set-Cookie: PHPSESSID=79c38493322374f1bc19541f4c538b02; expires=Mon,
07-Mar-2016 18:38:41 GMT; path=/; domain=www.mydomain.com; secure;
HttpOnly PHPSESSID=79c38493322374f1bc19541f4c538b02; expires=Mon,
07-Mar-2016 18:38:41 GMT; path=/
Second Call:
Set-Cookie: PHPSESSID=79c38493322374f1bc19541f4c538b02; expires=Mon, 07-Mar-2016 18:40:06 GMT; path=/
Related
Chrome and Microsoft IE are aborting a POST response but it's working fine in Firefox. When I run a test through Fiddler I notice the POST headers in Chrome/IE do not contain Cache-Control: max-age=0 and Origin: ... but are otherwise the same.
In Chrome when I press the submit button the POST is sent to the server, processed, and the client aborts the response. After a few reposts, the client finally accepts the response; however the server has already processed the request so it results in duplicate info. This never happens on Firefox, it just always accepts the first response.
It seems to only happen if the request is large (ie: contains a lot more fields for the server to process) leading me to think this has something to do with the time it takes for the server to process the request (in Firefox the request shows as taking about 9 seconds).
Is there something in Firefox that would cause it to wait longer for this response? Or vice-versa, something in IE/Chrome that could be making it end prematurely?
It may not be relevant but this is a Perl Mason site. The response headers in the page which has the form being submitted:
HTTP/1.1 200 OK
Date: Tue, 07 Aug 2018 19:08:57 GMT
Server: Apache
Set-Cookie: ...; path=/
Set-Cookie: TUSKMasonCookie=...; path=/
Expires: Mon, 1 Jan 1990 05:00:00 GMT
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
It turns out it was Javascript on the page responsible for the reposting. A setTimeout() which recursively called its own function was continuing to be set even after the form data had been posted within the method.
In Chrome/IE/Edge the form submission would be POSTed and the function would continue to set another timeout calling itself. The subsequent call would again POST and abort the connection waiting on the original.
Firefox however would not repost although it too would continue to set and recall the function.
The fix was to add a flag to track when the POST was submitted and when set, to stop the timeout cycle:
function countdown(secs, starttime) {
var d = new Date();
if (!starttime) {
starttime = d.getTime() / 1000;
}
var nowtime = d.getTime() / 1000;
var timeleft = (starttime + secs) - nowtime;
timeleft = Math.max(0, timeleft);
var isposted = false; // <-- Added as fix
if (timeleft == 0) {
isposted = true; // <-- Added as fix
alert("Time is up. Click OK.");
var frm = document.getElementById("frm");
frm.submit();
}
if (!isposted) { // <-- Added as fix
timeout = setTimeout(["countdown(", secs, ", ", starttime, ")"].join(""), 1000);
}
}
I have two subdomais "api.domain.com" and "web.domain.com".
Now "web.domain.com" is web page written in html/javascript and "api.domain.com" is a simple restful API server written in php.
"api.domain.com" sets certain cookies in the header as follows
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
setcookie("TestCookie", "Some Value", time()+3600, "/", ".domain.com", 0);
Now, when I make an ajax call (using jQuery.ajax() ) from "web.domain.com" to "api.domain.com", the response headers contain
Set-Cookie:abc=802691344656c1d0899c4a74.87956617; expires=Mon, 16-May-2016 21:00:09 GMT; path=/; domain=domain.com,
so i guess a cookie should be set in the client browser at "web.domain.com".
The next time I make another request to "api.domain.com" from "web.domain.com", shouldn't this cookie go as part of the request headers?
However, when I inspect the $_COOKIE array at "api.domain.com", i don't see this cookie! Does that mean the cookie never got set in the client ("web.domain.com") at the first place? What am I doing wrong?
Using the withCredentials header (as suggested by #charlietfl) worked for me. I had to make one more modification in the server as well.
So here's what I did.
In web.domain.com , while maqking the Ajax request, I added withCredentials: true , like this
$.ajax({
// The Url for the request
url : ajaxUrl,
// The data to send (will be converted to a query string)
data : ajaxData,
xhrFields: {
// To allow cross domain cookies
withCredentials: true
},
...
});
In api.domain.com , I set some headers like this :
header("Access-Control-Allow-Origin: *");
However, I was still unable to get any response. I got this error instead
Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.
So i simply set the header to the origin domain, like so :
$http_origin = $_SERVER['HTTP_ORIGIN'];
if (substr($input, -10) == 'domain.com') { // To check if request is always from a subdomain of 'domain.com'
header("Access-Control-Allow-Origin: $http_origin");
}
That fixed the issue.
i have ajax function like below:
$.ajax({
url:"cookie.php",
type: 'post',
data: {'ok': val},
success:function(data) {
alert(data);
}
});
and my cookie.php for setcookie is:
$name = "mySite";
$value = "stackoverflow.com";
setcookie($name, $value, time() + (86400 * 30), "/");
echo $name."=".$value;
with my ajax function mySite=stackoverflow.com show in my page but cookie not set in browser. why?
Cookies are set using the HTTP Set-Cookie header, sent in the HTTP response when a page first loads.
This header instructs the browser to store the cookie and send it back in future requests to the server.
When you set the cookie with ajax, the browser doesn't reload the current page, and no new headers are sent.
Instead, a new request is sent in the background with XMLHttpRequest, and the cookies are never added to the current page headers, as that page newer reloads and receives the header containing the cookie.
You have to reload the page and get a new set of headers to see the new cookies added in PHP.
There's also the option of setting the cookies in javascript, then they would be visible in the browser right away.
document.cookie="mySite=stackoverflow.com; expires=Thu, 18 Dec 2015 12:00:00 UTC; path=/";
Purpose:
I (a javascript beginner) am trying to perform a Rest API call to a web-server (Splunk) get data of content-type json. Call is initiated by angularjs based webApp, the problematic code snippet is posted below. The problem is investigated using firebug and the response & header information is mentioned below.
Angular Code Snippet:
$scope.onClickButton = function (button) {
$http({
method: 'POST',
url: 'https://localhost:8089/servicesNS/admin/search/search/jobs/export',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Splunk ' + $scope.sessionKey
},
data: {search: button.query, output_mode: 'json'}
}).success(function (response) {
alert("Success");
}).error(function (response) {
alert("error");// alerted error
alert(response); // alerts 'undefined'
});
};
Response Object (captured by firebug)
{"preview":false,"offset":0,"result":{"_serial":"0", "_sourcetype":"mylogger", "splunk_server":"mohit-PC"}}
{"preview":false,"offset":1,"result":{"_serial":"1", "_sourcetype":"mylogger", "splunk_server":"mohit-PC"}}
{"preview":false,"offset":2,"result":{"_serial":"2", "_sourcetype":"mylogger", "splunk_server":"mohit-PC"}}
...
Response Header
Access-Control-Allow-Head... Authorization
Access-Control-Allow-Meth... GET,POST,PUT,DELETE,HEAD,OPTIONS
Access-Control-Allow-Orig... *
Cache-Control no-store, no-cache, must-revalidate, max-age=0
Connection Keep-Alive
Content-Type application/json; charset=UTF-8
Date Tue, 02 Dec 2014 13:00:34 GMT
Expires Thu, 26 Oct 1978 00:00:00 GMT
Server Splunkd
Transfer-Encoding chunked
Vary Authorization
access-control-allow-cred... true
x-content-type-options nosniff
x-frame-options SAMEORIGIN
Firebug Error
Error: JSON.parse: unexpected non-whitespace character after JSON data at line 2 column 1 of the JSON data fromJson#angular.js:1054:9
.
Questions
Q1. The status of response is - 200 OK, then why the error is thrown? Though it is apparent that the response text does not represent a json object or an array of json objects. The [] and commas are absent. The server cannot be configured to respond with a proper formatted data. It seems angular does a format verification and throws exception. Can this verification be avoided/bypassed?
Q2. Even though the error occurred, why the response object is 'undefined' in http.error method? If it were not, I could do string manipulations as a work around.
I've read that it could be wise (for caching purposes) to call a file with it's last modified date and let the server resolve it to the original file. In this way you could set caching to for example 10 years and use a static name for a certain version of the file.
However since I also load in javascript asynchronously on my site, I need to be able to do the same in javascript/jQuery.
This is my current code, how would I be able to get the last-modified date of the script in question being loaded?
//load new js
if (typeof loadedScripts[url] === 'undefined') {
$.getScript("javascript/" + url + ".js", function() {
if (typeof window["load_" + url] !== 'undefined') {
promises = promises.concat(window["load_" + url](html));
}
loadedScripts[url] = 1;
});
}
else {
if (typeof window["load_" + url] !== 'undefined') {
promises = promises.concat(window["load_" + url](html));
}
}
(It also executes a function called on load, but that is not interesting for this question)
I know it is possible to get the last modified date of the current document with document.lastModified, but I'm unsure how it would translate into a $.getScript call.
I have also enabled caching:
//set caching to true
$.ajaxSetup({
cache: true
});
For caching purposes, I rather would suggest the ETag.
http://en.wikipedia.org/wiki/HTTP_ETag
We use it for busting the cache if needed and it works great.
However, jQuery's Ajax function provides an ifModified param:
http://api.jquery.com/jquery.ajax/
Here's the explanation:
Allow the request to be successful only if the response has changed
since the last request. This is done by checking the Last-Modified
header. Default value is false, ignoring the header. In jQuery 1.4
this technique also checks the 'etag' specified by the server to catch
unmodified data.
Using this param, the first request to get the Script would look like this:
GET /script.js HTTP/1.1
Host: www.orange-coding.net
HTTP/1.1 200 OK
Last-Modified: Wed, 02 Jan 2013 14:20:58 GMT
Content-Length: 4096
And a second request would look like this:
GET /script.js HTTP/1.1
Host: www.orange-coding.net
If-Modified-Since: Wed, 06 Oct 2010 08:20:58 GMT
HTTP/1.1 304 Not Modified