2
votes

All

This is a problem which happens rarely. In fact I had to spend a lot of time to reproduce it but here it is anyways.

I am using ASIHTTPRequest to get some data from my server. I throw error for anything apart from those having responseStatusCode == 200. My server returns some messages.

What I noticed is, that sometimes, depending on my wireless connection (on laptop simulator usage), the ones which needs authentication, ASIHttpRequest returns response of 200, but the responseData is something like the following instead of the messages from my server

<HTML><HEAD><TITLE>Cisco Systems Inc. Web Authentication Redirect</TITLE><META http-equiv="Cache-control" content="no-cache"><META http-equiv="Pragma" content="no-cache"><META http-equiv="Expires" content="-1"><META http-equiv="refresh" content="1; URL=https://webauth-redirect.oracle.com/login.html?redirect=17.22.111.222/scripts_dummy/messagesx.php"></HEAD></HTML>

Is this correct? If the message from the server was not received should not the responseStatusCode be something other than 200

How do I go about handling this kind of situation? meaning after checking responseStatusCode == 200 does not seem to be good enough. This was just an example. In other wireless regions, different garbage is printed out.

UPDATE Not sure if this has any role to play but I have

request.shouldUseRFC2616RedirectBehaviour = YES; // where request is ASIHTTPRequest
3

3 Answers

3
votes

That's not ASIHTTPRequest or your client code's fault. That's the server expecting the client to be a web browser and sending it a a meta refresh redirect (that is, an HTML page with a redirect embedded in it) rather than an HTTP 30x, which ASIHTTP would have handled for you.

This is an excellent example of how meta refresh has been abused: it was meant to refresh the current page, but people started using it to send the client somewhere else, which was what HTTP 30x was already designed for. Googling for "meta refresh vs 301 redirect" will give you plenty of blog posts making the arguments.

In your case, unless you can get your server to behave friendlier to non-browser clients, you'll need to check for this condition yourself when response code is 200, parse out the redirect and re-issue the request yourself.

1
votes

After thinking about this for a few, I've come up with an alternate strategy. Content type will be preserved and should not be muddled with.

You should be able to use the content type as a flag that you are receiving a proxy injected page. Set a content type parameter then have your app key off that parameter. Any responses that don't have the parameter are invalid.

$content_type = 'text/html; FooCorp-MyApp=true'

BTW: why are you using a content type of text/html if you don't properly support HTML processing. Meta refresh should be a part of any HTML engine. If you don't need HTML, you may want do consider using a data specific content type like XML, YAML, or JSON.


The question has been raised, "is that valid?"

From RFC 2616: 3.7 Media Types

The type, subtype, and parameter attribute names are case- insensitive. Parameter values might or might not be case-sensitive, depending on the semantics of the parameter name. Linear white space (LWS) MUST NOT be used between the type and subtype, nor between an attribute and its value. The presence or absence of a parameter might be significant to the processing of a media-type, depending on its definition within the media type registry.

Note that some older HTTP applications do not recognize media type parameters. When sending data to older HTTP applications, implementations SHOULD only use media type parameters when they are required by that type/subtype definition.

To me, the takeaway from that is don't send non-standard parameters to older clients. In context, it means you're safe if you are sending it to any client made since 2000.

0
votes

I ended up passing a special key/value pair in my response header to make sure the client understands the response is from my server and not from some intermediary redirection.

function sendResponse($status = 200, $body = '', $content_type = 'text/html')
{
   $status_header = 'HTTP/1.1 ' . $status . ' ' . getStatusCodeMessage($status);
   header($status_header);
   header('Content-type: ' . $content_type);
   $value = 'success';
   header('myApp:' . $value); // --> I will always check in my client that the key myApp has the value success

echo $body;
}