Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-16154] Android: XHR GZip 200 response code handled as error

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2014-01-15T01:57:53.000+0000
Affected Version/sRelease 3.1.3, Release 3.2.0
Fix Version/s2014 Sprint 01, 2014 Sprint 01 Core, Release 3.3.0
ComponentsAndroid
Labelsgzip, module_android, qe-testadded
ReporterMarco Cota
AssigneeDaniel Fortner
Created2014-01-09T16:35:46.000+0000
Updated2014-06-12T00:03:17.000+0000

Description

Issue

When receiving Gzipped responses on Android this are being incorrectly handled as http errors by the titanium SDK even when the response code is 200 or 201. This is only happening when the response have an empty body.

Logs

Gzip Response
[INFO] :   Gzip Enabled
[WARN] :   IdleConnectionHandler: Removing a connection that never existed!
[ERROR] :  TiHttpClient: (TiHttpClient-23) [360048,1780592] HTTP Error (java.io.EOFException): java.io.EOFException
[ERROR] :  TiHttpClient: java.io.EOFException
[ERROR] :  TiHttpClient: 	at java.util.zip.GZIPInputStream.readFully(GZIPInputStream.java:202)
[ERROR] :  TiHttpClient: 	at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:98)
[ERROR] :  TiHttpClient: 	at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:81)
[ERROR] :  TiHttpClient: 	at ti.modules.titanium.network.TiHTTPClient$LocalResponseHandler.handleResponse(TiHTTPClient.java:268)
[ERROR] :  TiHttpClient: 	at ti.modules.titanium.network.TiHTTPClient$LocalResponseHandler.handleResponse(TiHTTPClient.java:217)
[ERROR] :  TiHttpClient: 	at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657)
[ERROR] :  TiHttpClient: 	at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:637)
[ERROR] :  TiHttpClient: 	at ti.modules.titanium.network.TiHTTPClient$ClientRunnable.run(TiHTTPClient.java:1287)
[ERROR] :  TiHttpClient: 	at java.lang.Thread.run(Thread.java:841)
[INFO] :   XHR RESPONSE Error >>> Response:
[INFO] :   XHR RESPONSE Error >>> Status: 200 Type: POST Headers: Date:Thu, 09 Jan 2014 16:01:28 GMT
[INFO] :   Server:Apache
[INFO] :   Content-Encoding:gzip
[INFO] :   Content-Length:0
[INFO] :   Keep-Alive:timeout=10, max=30
[INFO] :   Connection:Keep-Alive
[INFO] :   Content-Type:image/png
[DEBUG] :  HTTPClient: The persistent handle is disposed.
Non Gzip Response
[INFO] :   Gzip Disabled
[INFO] :   XHR RESPONSE Load >>> Response: "null"
[INFO] :   XHR RESPONSE Load >>> Status: 200 Type: POST Headers: Date:Thu, 09 Jan 2014 16:00:45 GMT
[INFO] :   Server:Apache
[INFO] :   Content-Length:0
[INFO] :   Vary:Accept-Encoding
[INFO] :   Keep-Alive:timeout=10, max=30
[INFO] :   Connection:Keep-Alive
[INFO] :   Content-Type:image/png; charset: UTF-8
[DEBUG] :  HTTPClient: The persistent handle is disposed.

Steps to Reproduce

1. Run the test case 2. Click on Non Gzip Button 3. Receive a load response from the xhr 4. Click Gzip Button 5. Receive an error response from the xhr The php server return the same body empty response with the difference of the gzip encoding header

Sample Code


var win = Ti.UI.createWindow();
var bt1 = Ti.UI.createButton({
	title:'NonGZIP',
	width:80,
	left:10,
	gzip:false,
	bottom:10
});
var bt2 = Ti.UI.createButton({
	title:'GZIP',
	width:80,
	right:10,
	gzip:true,
	bottom:10
});
bt1.addEventListener('click',doRequest);
bt2.addEventListener('click',doRequest);

win.add(bt1);
win.add(bt2);
win.open();
function doRequest(e){
	var xhr = Ti.Network.createHTTPClient(); 
	
	xhr.onload = function(e){
	    Titanium.API.info('XHR RESPONSE Load >>> Response: "'+this.responseText+'"');
	    Titanium.API.info('XHR RESPONSE Load >>> Status: '+this.status+' Type: '+ this.connectionType+' Headers: '+ this.allResponseHeaders);
	};
	
	xhr.onerror = function(e){
	    Titanium.API.info('XHR RESPONSE Error >>> Response: '+this.responseText);
	    Titanium.API.info('XHR RESPONSE Error >>> Status: '+this.status+' Type: '+ this.connectionType+' Headers: '+ this.allResponseHeaders);
	};
	
	try {	
		xhr.open('POST','http://demo.cotaman.com/gzip.php');
		xhr.setRequestHeader('User-Agent', Ti.userAgent);
		xhr.setRequestHeader('x-cmk-agent', 'M3 v' + Ti.App.version);
		if(e.source.gzip){
			xhr.setRequestHeader('Accept-Encoding', 'gzip,deflate');
			Ti.API.info('Gzip Enabled');
		}else{
			Ti.API.info('Gzip Disabled');
		}
		var imageFile = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory,'image.jpg');
        if(imageFile.exists()) {
          	xhr.send({
	            media: imageFile.read(),
	            test: 'pic_'
         	});
        }
	} catch(e) {
	    currentAction = null;
	    Ti.API.info('ERROR : '+e.message);
	}
};


Sample App at https://www.dropbox.com/s/dhd9czzl5u488ft/testcase.zip

Comments

  1. Allen Yeung 2014-01-14

    Test case to verify that GZIP works:
       Ti.UI.backgroundColor = '#dddddd';
         
       var url = "https://raw.github.com/appcelerator/titanium_mobile/master/package.json";
       var win = Ti.UI.createWindow();
         
       var xhr = Ti.Network.createHTTPClient({
           onload: function() {
           Ti.API.debug(this.responseText);
            
           },
           onerror: function(e) {
           Ti.API.debug("STATUS: " + this.status);
           Ti.API.debug("TEXT:   " + this.responseText);
           Ti.API.debug("ERROR:  " + e.error);
           alert('There was an error retrieving the remote data. Try again.');
           },
           timeout:5000
       });
        
        
       xhr.open("GET", url);
       xhr.setRequestHeader("Accept-Encoding","gzip,deflate"); 
       xhr.send();
         
       win.open();
       
  2. Allen Yeung 2014-01-14

    Master PR: https://github.com/appcelerator/titanium_mobile/pull/5214 Please test both original, and second test case to verify that gzip still works.
  3. Lokesh Choudhary 2014-05-06

    Verified the fix. We see XHR GZip 200 response as expected in the console & do not see any errors. Environment: Appc Studio : 3.2.3.201404181520 Ti SDK : 3.3.0.v20140502133323 Mac OSX : 10.8.5 Alloy : 1.3.1 CLI - 3.2.3 Nexus 5 - android 4.4.2

JSON Source