Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-14024] Android: HttpClient does not redirect POST requests correctly (they become GET)

GitHub Issuen/a
TypeBug
PriorityLow
StatusClosed
ResolutionInvalid
Resolution Date2013-06-24T16:51:22.000+0000
Affected Version/sn/a
Fix Version/s2013 Sprint 13 API, 2013 Sprint 13
ComponentsAndroid
Labelsn/a
ReporterDavide Cassenti
AssigneeIngo Muschenetz
Created2013-05-30T15:50:23.000+0000
Updated2017-03-09T19:06:09.000+0000

Description

Description of the problem

When sending a request using POST, if the server returns a redirect, the next request is made using GET. Disabling autoRedirect also doesn't work, as the result status is 200 and not 3xx

Steps to reproduce

You need a server that returns a 3xx status (e.g. 302). In my server code, the page where you redirect will print out the method (get or post). The Titanium code would be:
var xhr = Ti.Network.createHTTPClient({
	onload: function(e) {
		alert(this.responseText);
	}
});

xhr.open('POST', URL_WITH_REDIRECT);
xhr.send();

Server code sample (PHP)

page.php
<?php
header('Location: newpage.php',true,302);
exit;
newpage.php
<?php
var_dump($_SERVER['REQUEST_METHOD']);

Comments

  1. Ping Wang 2013-06-17

    On Android, we use Apache HttpClient which handles all types of redirects automatically. The behavior that converts redirects of PUT/POST to GET is actually on purpose. Here is the [ticket](https://issues.apache.org/jira/browse/HTTPCLIENT-860) on Apache's JIRA website. From the comments in that ticket, we can see there is a history of debate on which behavior is correct/expected. Our current Android behavior follows the default Apache HttpClient behavior.
  2. Davide Cassenti 2013-06-24

    The workaround is to run more calls, depending on the result of the first one. If the first call is a 30x, you need to read the header, and perform another call with the new url. The first call would be to the original url:
       xhr.open("POST", "FIRST_URL");
       xhr.autoRedirect = false;
       xhr.send();
       
    Then, need to read the headers in the 'onerror' callback (this is due to TIMOB-13930):
       onerror: function(e) {
           var headers = this.getAllResponseHeaders();
           headers = headers.split("\n");
       
           var newLocation = null;
           for (var h=0; h<headers.length; h++) {
               if (headers[h].indexOf("Location") != -1) {
                   newLocation = headers[h].substr(headers[h].indexOf(":")+1).trim();
                   break;
               }
           }
       
           if (newLocation != null) {
               // perform the second call here
           }
       
       }
       
    Then need to perform a new xhr call to newLocation
  3. Hieu Pham 2013-06-24

    Closing this ticket as invalid, since this is expected behavior.
  4. Lee Morris 2017-03-09

    Closing ticket as invalid.

JSON Source