Can varnish cache be hacked? - caching

Today index pages of two my domains (9 domains altogether) were redirected to amazon page. All other pages worked fine. Websites are custom coded.
First thought was websites were hacked, but I didn't find a single file modified within last 24 hours. I went through other possible options and nothing.
The last unknown was varnish installed a couple weeks ago.
In result after restarting varnish/clearing the cache redirection stopped...
So the question is can varnish cache be modified from outside ?
I'm not a varnish expert since it sits on my server for a very short time, as well I'm aware that my config file is probably a mess but any suggestions are appreciated.
Thank you,
derek
UPDATE:
Thank you for answer.
Once cache is refreshed and redirection is removed, the next day other domains are affected in the same way.
Purging single url '/' removes redirection until next time.
I set a script checking page status to get exact time when it occurs. Got the time but cannot find much in logs. No varnish commands in syslog.
Now it happens on two physical vps servers, with exact the same source code.
Below are a few lines from varnishncsa, where HEAD request is my script, first header returns status 200 and the last is redirected - 302 to amazon.
1.2.3.4 - - [11/Jun/2016:22:40:23 -0400] "HEAD http://www.domain.com/ HTTP/1.1" 200 0 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.
7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
107.170.81.129 - - [11/Jun/2016:22:40:29 -0400] "GET http://www.domain.ca/search/?catid=1&sub_catid=22&sub_sub_catid=34 HTTP/1.1" 200 5908 "http:
//www.domain.com/categories/sitemap/" "Mozilla/5.0 (compatible; spbot/5.0.2; +http://OpenLinkProfiler.org/bot )"
100.43.81.151 - - [11/Jun/2016:22:40:39 -0400] "GET http://www.domain.com/ HTTP/1.1" 302 205 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex
.com/bots)"
100.43.91.12 - - [11/Jun/2016:22:40:39 -0400] "GET http://www.domain.com/robots.txt HTTP/1.1" 302 205 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +
http://yandex.com/bots)"
100.43.81.151 - - [11/Jun/2016:22:40:39 -0400] "GET http://domain.com/robots.txt HTTP/1.1" 301 0 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http:
//yandex.com/bots)"
100.43.81.151 - - [11/Jun/2016:22:40:39 -0400] "GET http://domain.com/robots.txt HTTP/1.1" 301 0 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://ya
ndex.com/bots)"
100.43.81.151 - - [11/Jun/2016:22:40:41 -0400] "GET http://www.domain.com/ HTTP/1.1" 200 4046 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://y
andex.com/bots)"
100.43.91.12 - - [11/Jun/2016:22:40:41 -0400] "GET http://domain.com/ HTTP/1.1" 301 0 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.co
m/bots)"
100.43.81.151 - - [11/Jun/2016:22:40:41 -0400] "GET http://domain.com/ HTTP/1.1" 301 0 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/b
ots)"
68.180.228.126 - - [11/Jun/2016:22:40:48 -0400] "GET http://www.domain.ca/profile/Faro HTTP/1.1" 200 7060 "-" "Mozilla/5.0 (compatible; Yahoo! Slurp;
http://help.yahoo.com/help/us/ysearch/slurp)"
104.193.88.243 - - [11/Jun/2016:22:40:55 -0400] "GET http://www.domain.uk/search/?catid=377&sub_catid=448&sub_sub_catid=461 HTTP/1.1" 200 33613 "-
" "Mozilla/5.0 (Windows NT 5.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2"
117.78.13.18 - - [11/Jun/2016:22:41:13 -0400] "GET http://www.domain.com/robots.txt HTTP/1.0" 200 405 "-" "nutch-1.4/Nutch-1.4"
1.2.3.4 - - [11/Jun/2016:22:41:23 -0400] "HEAD http://www.domain.com/ HTTP/1.1" 302 0 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.
7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
And here are headers when redirection occurs:
Request URL: http://www.example.com/
Request method: GET
Remote address: 1.2.3.4:80
Status code: 302 Found
Version: HTTP/1.1
Request headers:
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Response headers:
Age: 37681
Cache-Control: public
Connection: keep-alive
Content-Length: 205
Content-Type: text/html; charset=iso-8859-1
Date: Sun, 12 Jun 2016 02:40:41 GMT
Location: http://www.amazon.com
Server: Apache
Via: 1.1 varnish-v4
X-Varnish: 1249239 1443890
Request URL: http://www.amazon.com/
Request method: GET
Remote address: 54.239.25.200:80
Status code: 301 MovedPermanently
Version: HTTP/1.1
Request headers:
Host: www.amazon.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Response headers:
Content-Encoding: gzip
Content-Type: text/html; charset=ISO-8859-1
Date: Sun, 12 Jun 2016 13:08:43 GMT
Location: https://www.amazon.com/179-0743706-1316952
P3P: policyref="https://www.amazon.com/w3c/p3p.xml",CP="CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA
All domains have been online for about 2 years without any problems, and varnish was installed 2 weeks ago.
For now I was forced to pass 'index' and if no solution is found will try to downgrade varnish to see if that helps.
Besides I have no clue where to start, what and where to look for ???
Below is my default.vcl file
vcl 4.0;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "2.3.4.5";
.port = "8080";
.first_byte_timeout = 300s;
.connect_timeout = 5s;
.between_bytes_timeout = 60s;
}
acl allowed_ip {
# Access Control List used to to warm up cahe
"1.2.3.0/22";
"2.3.4.5";
}
sub vcl_recv {
# Do not cache
if ( req.url ~ "^/sitemap-(index|ads|profiles|static)\.xml")
{ return( pass ); }
# Do not allow external access
if (req.url ~ "^/(crone_job|sitemap_generator)\.php" && !client.ip ~ allowed_ip)
{
set req.url = "/";
}
# Detect device and redirect to proper site
if ( (req.http.host ~ "www\.domain\.(ca|com|uk)" ||
req.http.host ~ "^domain\.(ca|com|uk)" ) &&
!(req.url ~ "\.(jpg|jpeg|png|gif|bmp|mp4|ogv|webm|m4a|ogg|doc|docx|xls|xlsx|pps|ppt|pptx|txt|rtf|csv|xml|pdf|zip|odf|ods)$" )) {
call device_detection;
}
# Redirect non-www domain to www
if (req.http.host ~ "^domain\.(ca|com|uk)$") {
return (synth (750, ""));
}
# Only deal with "normal" types
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "PATCH" &&
req.method != "DELETE") {
# /* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
# Only cache GET or HEAD requests. This makes sure the POST requests are always passed.
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# First remove the Google Analytics added parameters, useless for our backend
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
set req.url = regsub(req.url, "\?&", "?");
set req.url = regsub(req.url, "\?$", "");
}
# Remove the "has_js" cookie
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
# Remove any Google Analytics based cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
if (req.http.Cookie ~ "user_name=" || req.http.Cookie == "registeredDevice") {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID|user_name|registeredDevice)=", "; \1=");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
if (req.http.Cookie == "") {
unset req.http.Cookie;
}
}
# Post requests will not be cachedre there cookies left with only spaces o
# r that are empty?
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
# Remove all cookies for static files
if (req.url ~ "^[^?]*\.(css|jpeg|jpg|js|txt|ico)(\?.*)?$"){
unset req.http.Cookie;
return (hash);
}
if (req.url ~ "^/image.php." ||
req.url ~ "publication.php" ||
req.url ~ "google_map.php" ) {
unset req.http.Cookie;
}
# Send Surrogate-Capability headers to announce ESI support to backend
set req.http.Surrogate-Capability = "key=ESI/1.0";
# if (req.http.Authorization || req.method == "POST") {
if ( req.method == "POST") {
return (pass);
}
# Normalizing namespace
if (req.http.host ~ "(?i)^(www.)?domain.ca") {
set req.http.host = "www.domain.ca"; }
if (req.http.host ~ "(?i)^(www.)?domain.com") {
set req.http.host = "www.domain.com"; }
if (req.http.host ~ "(?i)^(www.)?domain.uk") {
set req.http.host = "www.domain.uk"; }
# the script varnish-cache-warmup.sh must always refresh the cache
if (client.ip ~ allowed_ip && req.http.Cache-Control ~ "no-cache") {
set req.hash_always_miss = true;
}
}
sub vcl_backend_response {
if(
bereq.url == "/" ||
bereq.url == "/about-us/" ||
bereq.url == "/contact/" ||
bereq.url == "/blog/" ||
bereq.url == "/categories/sitemap/" ||
bereq.url == "/help/"
){
# cache, ignoring any cache headers
set beresp.ttl = 24h;
unset beresp.http.Pragma;
unset beresp.http.Set-Cookie;
set beresp.http.Cache-Control = "public"; # max-age=0; s-maxage=1800";
unset beresp.http.Expires;
set bereq.http.Cookie = regsuball(bereq.http.Cookie, "PHPSESSID=[^;]+(; )?", "");
unset bereq.http.Cookie;
}
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
# Enable cache for all static files
if (bereq.url ~ "^[^?]*\.(css|jpeg|jpg|js|txt|ico)(\?.*)?$") {
unset beresp.http.set-cookie;
}
if (bereq.url ~ "^/image.php.") {
unset beresp.http.set-cookie;
}
# Varnish 4 fully supports Streaming, so use streaming here to avoid locking.
if (bereq.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") {
unset beresp.http.set-cookie;
set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects
set beresp.do_gzip = false; # Don't try to compress it for storage
}
# Set 2min cache if unset for static files
if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
set beresp.ttl = 120s; # Important, you shouldn't rely on this, SET YOUR HEADERS in the backend
set beresp.uncacheable = true;
return (deliver);
}
# Don't cache 50x responses
if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504 || beresp.status == 403) {
return (abandon);
}
# Allow stale content, in case the backend goes down.
# make Varnish keep all objects for 6 hours beyond their TTL
set beresp.grace = 6h;
return (deliver);
}
sub vcl_deliver {
}
sub vcl_synth {
# Redirect non-www domain to www
if (resp.status == 750) {
set resp.status = 301;
set resp.http.Location = "http://www." + req.http.host + req.url;
return(deliver);
}
# Redirect to mobile site
if (resp.status == 751) {
set resp.status =301;
set req.http.host = regsub(req.http.host, "^www\.","");
set resp.http.Location = "http://m." + req.http.host + req.url;
return(deliver);
}
}
sub device_detection {
set req.http.X-Device = "pc";
if (req.http.User-Agent ~ "iP(hone|od)" ||
req.http.User-Agent ~ "Android" ||
req.http.User-Agent ~ "Symbian" ||
req.http.User-Agent ~ "^BlackBerry" ||
req.http.User-Agent ~ "^SonyEricsson" ||
req.http.User-Agent ~ "^Nokia" ||
req.http.User-Agent ~ "^SAMSUNG" ||
req.http.User-Agent ~ "^LG" ||
req.http.User-Agent ~ "webOS")
{ set req.http.X-Device = "mobile"; }
if (req.http.User-Agent ~ "^PalmSource")
{ set req.http.X-Device = "mobile"; }
if (req.http.User-Agent ~ "Build/FROYO" ||
req.http.User-Agent ~ "XOOM" ) {
set req.http.X-Device = "pc";
}
if (req.http.X-Device == "mobile") {
return (synth(751, ""));
}
}

Varnish is just software like any other, so guarantees are hard to make.
If you judge by earlier incidents, Varnish has a very good security history and appears to be mostly safe.
As far as your VCL goes, there is nothing in there that allows for the behaviour you describe. In fact it would be very hard to introduce something like this on the Varnish level, as Varnish doesn't normally support rewriting/changing response bodies.

Related

Cache content of Ajax Get call in varnish 5.2

I am new in varnish and using Varnish 5.2 and want to know why Varnish do not cache AJAX Get request while it does cache the content if same Ajax call is requested through a URL call from browser.
Following is the default.vcl file
vcl 4.0;
import std;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
# Normalize the header, remove the port (in case you're testing this on various TCP ports)
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
# Remove the proxy header (see https://httpoxy.org/#mitigate-varnish)
unset req.http.proxy;
# Normalize the query arguments
set req.url = std.querysort(req.url);
# Allow purging
if (req.method == "PURGE") {
# If you got this stage (and didn't error out above), purge the cached result
return (purge);
}
# Some generic cookie manipulation, useful for all templates that follow
# Remove the "has_js" cookie
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "PHPSESSID=[^;]+(; )?", "");
# Remove any Google Analytics based cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
# Remove DoubleClick offensive cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");
# Remove the Quant Capital cookies (added by some plugin, all __qca)
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
# Remove the AddThis cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", "");
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
if (req.url ~ "^[^?]*\.(7z|avi|bz2|flac|flv|gz|mka|mkv|mov|mp3|mp4|mpeg|mpg|ogg|ogm|opus|rar|tar|tgz|tbz|txz|wav|webm|xz|zip)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
if (req.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|otf|ogg|ogm|opus|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
if (req.http.X-Requested-With == "XMLHttpRequest"){
return (hash);
}
set req.http.Surrogate-Capability = "abc=ESI/1.0";
return (hash);
}
sub vcl_backend_response {
set beresp.grace = 1200s;
set beresp.ttl = 120s;
if (beresp.http.Surrogate-Control ~ "ESI/1.0")
{ unset beresp.http.Surrogate-Control; // for Varnish >= 3.0 set beresp.do_esi = true; // for Varnish < 3.0 // esi;
}
}
Following is the response of varnishlog command file
* << Request >> 98313
- Begin req 98311 rxreq
- Timestamp Start: 1523473475.288141 0.000000 0.000000
- Timestamp Req: 1523473475.288141 0.000000 0.000000
- ReqStart 192.168.33.1 39288
- ReqMethod GET
- ReqURL /get-test/sf1102505aabc133ddbae?customerId=110250
- ReqProtocol HTTP/1.1
- ReqHeader Host: test-website.test
- ReqHeader Connection: keep-alive
- ReqHeader Pragma: no-cache
- ReqHeader Cache-Control: no-cache
- ReqHeader Accept: */*
- ReqHeader X-Requested-With: XMLHttpRequest
- ReqHeader User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
- ReqHeader Referer: http://test-website.test/get-widget-110250-ProductID1
- ReqHeader Accept-Encoding: gzip, deflate
- ReqHeader Accept-Language: en,es;q=0.9,en-US;q=0.8
- ReqHeader Cookie: PHPSESSID=e41a91kihnchjn9c4aor07jl3p
- ReqHeader X-Forwarded-For: 192.168.33.1
- VCL_call RECV
- ReqUnset Host: test-website.test
- ReqHeader Host: test-website.test
- ReqURL /get-test/sf1102505aabc133ddbae?customerId=110250
- ReqUnset Cookie: PHPSESSID=e41a91kihnchjn9c4aor07jl3p
- ReqHeader Cookie: PHPSESSID=e41a91kihnchjn9c4aor07jl3p
- ReqUnset Cookie: PHPSESSID=e41a91kihnchjn9c4aor07jl3p
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- VCL_return hash
- ReqUnset Accept-Encoding: gzip, deflate
- ReqHeader Accept-Encoding: gzip
- VCL_call HASH
- VCL_return lookup
- VCL_call MISS
- VCL_return fetch
- Link bereq 98314 fetch
- Timestamp Fetch: 1523473475.452031 0.163890 0.163890
- RespProtocol HTTP/1.1
- RespStatus 200
- RespReason OK
- RespHeader Date: Wed, 11 Apr 2018 19:04:35 GMT
- RespHeader Server: Apache/2.4.7 (Ubuntu)
- RespHeader Access-Control-Allow-Origin: *
- RespHeader Access-Control-Allow-Credentials: true
- RespHeader Cache-Control: max-age=300, public
- RespHeader X-Cache-Debug: 1
- RespHeader Pragma: cache
- RespHeader X-Debug-Token: 4dda3e
- RespHeader X-Debug-Token-Link: http://test-website.test/_profiler/4dda3e
- RespHeader Vary: Accept-Encoding
- RespHeader Content-Encoding: gzip
- RespHeader Content-Length: 2039
- RespHeader Content-Type: text/css; charset=UTF-8
- RespHeader X-Varnish: 98313
- RespHeader Age: 0
- RespHeader Via: 1.1 varnish (Varnish/5.2)
- VCL_call DELIVER
- VCL_return deliver
- Timestamp Process: 1523473475.452071 0.163930 0.000039
- RespHeader Accept-Ranges: bytes
- RespHeader Connection: keep-alive
- Timestamp Resp: 1523473475.452225 0.164084 0.000155
- ReqAcct 589 0 589 527 2039 2566
- End
Remember: It gets a HIT if call directly from browser
do you have a varnishlog of the normal GET request - aka from the browser
i suspect that the xmlhttprequest - sends:
- ReqHeader Pragma: no-cache
- ReqHeader Cache-Control: no-cache
you either remove the 2 headers in vcl_recv by unsetting them:
sub vcl_recv {
unset req.http.Pragma;
unset req.http.Cache-Control;
}
or you disable it in the application itself. for example if you are using jquery
$.ajaxSetup({
cache: true
});
but depends on how you do the ajax requests.

Getting 400 Bad Request error Spring mvc + angular JS ajax request

This is my ajax request
$scope.check = function(ids) {
$http.post("logreport/move", {"ids":ids})
.success(function(data, status, headers, config) {
$scope.data = data;
}).error(function(data, status, headers, config) {
$scope.status = status;
});
};
& this is my controller
#RequestMapping(value = "/move", method = RequestMethod.POST)
public #ResponseBody
GenericResponse move(#RequestParam(value = "ids") String ids
) {
try {
System.out.println(ids);
} catch (Exception ex) {
System.out.println("INSIDE FAILED");
ex.printStackTrace(System.out);
return new GenericResponse("Failed", ex.getMessage(), 500);
}
return new GenericResponse("Success", "", 200);
}
Js logs
Remote Address:::1:8081
Request URL:http://localhost:8081/test/logreport/move
Request Method:POST
Status Code:400 Bad Request
Request Headersview
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:15
Content-Type:application/json;charset=UTF-8
Host:localhost:8081
Origin:http://localhost:8081
Referer:http://localhost:8081/test/
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payloadview
{ids:[ 1]}
ids: [ 1]
Response Headersview
Connection:close
Content-Length:971
Content-Type:text/html;charset=utf-8
Date:Mon, 12 May 2014 11:19:28 GMT
Server:Apache-Coyote/1.1

IE lags on sending POST data

Recently I found very strange behavior of IE8/9 when sending XHR data. I'd like to ask you if you have ever seen such behavior? Is it IE bug? How can I protect my server from "empty" request generated by IE? Here are more details:
I found out that when your page tries to send XHR data and JavaScript freezes or lags browser, IE lags sending POST data to server. To make it clear, here are steps to reproduce:
Create simple server which dumps POSTs received. I've used Node.JS for tests. You can find corresponding codes at the bottom of the post.
Open localhost:8080 in IE, open debug window and start debuging scripts with breakpoint set in line 51 of file localhost:8080
Hit Send by JQuery. You should have your javascript waiting on the breakpoint and server logged message:
--------------------------------------
14:04:19
REQUEST: /
HTTP HEADER:
accept = text/html, application/xhtml+xml, */*
accept-language = pl-PL
user-agent = Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
accept-encoding = gzip, deflate
host = localhost:8080
connection = Keep-Alive
--------------------------------------
14:04:35
REQUEST: /test
HTTP HEADER:
accept = */*
content-type = application/json
x-requested-with = XMLHttpRequest
referer = http://localhost:8080/
accept-language = pl
accept-encoding = gzip, deflate
user-agent = Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
host = localhost:8080
content-length = 24
connection = Keep-Alive
cache-control = no-cache
When you release JavaScript from the breakpoint server reports incoming data by new line:
POST: {"data1":10,"data2":123}
I've done the same test on Opera 12.15 and Chrome 27.0.1453.94 m and, as expected, POST data are sent immediately.
-- source codes --
Code for node.js server:
var http = require('http');
var qs = require('querystring');
var fs = require('fs');
http.createServer(function (req, res) {
console.log('--------------------------------------');
console.log(new Date().toLocaleTimeString());
console.log('REQUEST: ' + req.url);
console.log('HTTP HEADER: ');
for (var header in req.headers) {
console.log(' ' + header + ' = ' + req.headers[header]);
}
switch (req.method) {
case 'POST':
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end', function() {
console.log('POST: ' + body);
});
res.writeHead(200, {'Content-type': 'application/json'});
res.end(JSON.stringify({ succeeded: true, value: 'Hello world!' }));
break;
case 'GET':
fs.readFile('./servertest.html', function (err, data) {
if (err) {
throw err;
}
res.writeHeader(200, {'Content-type': 'text/html'});
res.end(data);
});
break;
}
}).listen(8080, 'localhost');
console.log('listening on localhost:8080');
Code for servertest.html:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<button onclick="send()">Send by JQuery</button>
<button onclick="sendXHR()">Send by XHR</button>
</body>
<script type="text/javascript">
var _xhr;
function sendXHR() {
_xhr = new XMLHttpRequest();
new XHRStateChangeListener();
var url = '/testXHR';
var method = 'POST';
_xhr.open(method, url);
_xhr.setRequestHeader("Content-Type", "application/json");
_xhr.send(JSON.stringify({test: 'this is a test', aoawiejf:23423}));
}
function XHRStateChangeListener() {
callback = function() {
var msg;
if (_xhr.readyState == 4 && /200|304/.test(_xhr.status)) {
alert('ready: ' + _xhr.responseText);
}
};
_xhr.onreadystatechange = callback;
}
function send() {
$.ajax({
url: '/test',
type: 'POST',
data: JSON.stringify({data1: 10, data2: 123}),
contentType: 'application/json',
error: function(xhr, status, err) {
alert('Error: ' + err + '\nStatus: ' + status);
},
success: function (data) {
alert('succeeded! data: ' + data);
}
});
}
</script>
</html>
You are using sync-mode, right is async-mode:
replace
_xhr.open(method, url);
by
_xhr.open(method, url, true);//Async mode
Note: Remember "onreadystatechange" is only for async-mode
the problem may also be in this function (just a guess):
JSON.stringify
try sending empty data, ie: data:""

django with ssl redirect and ajax post gives a 301 error

I am using this django snippet [1] to redirect to my https website. I know it does not work with POST requests so I did not add the {'SSL': True } in the all the url POST requests in my urls.py. However I always get a 301 error (in my access logs), although the view does what it is asked to do.
The view is 'called' by an ajax request and returns a json object.
def confirm(request, username):
if username == request.user.username:
user = get_object_or_404(User, username=username)
if request.method == 'POST':
response_dict = {
'status': True,
'added_total': count,
'username': username,
'message': message
}
return HttpResponse(simplejson.dumps(response_dict), mimetype='application/javascript')
else:
return HttpResponseRedirect('/fx/%s?page=%s' % (username, '1'))
else:
raise Http404(u'Not a valid user')
I also tried to add the {'SSL': True} argument but I still get the 301 error.
for ajax post requests I also use this snippet:
$.ajaxSetup({
beforeSend:function (xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != "") {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
What am I doing wrong?
EDIT: This is my action from urls.py
url(r'^confirm/(\w+)/$', confirm),
[1] http://djangosnippets.org/snippets/85/

AJAX Ready State 4, but empty text

I call a page using AJAX, requesting a search for something. But the response text is always empty, although the ready state is 4.
function process() {
var requestPage = "http://some.page/search.php";
var xmlHTTP;
var searchString = "test";
if (window.XMLHttpRequest) {
xmlHTTP = new XMLHttpRequest();
} else {
xmlHTTP = new ActiveXObject("Microsoft.XMLHTTP");
}
var results;
xmlHTTP.open("GET", requestPage + "?search=" + searchString, true);
xmlHTTP.send();
xmlHTTP.onreadystatechange = function() {
results = xmlHTTP.responseText;
alert("r: " + results + " rs: " + xmlHTTP.readyState + " st: " + xmlHTTP.status);
}
}
The results I get from this are
r: rs: 2 st: 0
r: rs: 4 st: 0
So, the request is done successfully, but the HTTP status isn't 200. But: I tracked the request using WireShark and the result package of the request shows as status 200 and even contains the complete result of the request, see below:
7014 190.663287 some.page local.pc HTTP HTTP/1.1 200 OK (text/html)
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=xxx; Path=/xxx
Content-Type: text/html;charset=iso-8859-1
Content-Length: 3108
Date: Tue, 19 Apr 2011 13:05:41 GMT
<html>
<head>
<title>Search</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white">
...
So; why don't I get the status 200 on my AJAX request when it obviously succeded?
So your problem is that you are requesting a page with a different port.
The same origin policy says that the protocol, port and host should be the same.
See
http://en.wikipedia.org/wiki/Same_origin_policy and https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript

Resources