Thursday, October 2, 2008

Flash HTTP Client Limitations

Flash currently has no legitimate HTTP client when running within a browser. If your Flash browser application needs to integrate with a REST service, you may find your self having to write a bunch of extra code to work around Flash's limitations. Your two options when using the Flash APIs are flash.net.URLLoader and mx.rpc.http.HTTPService. HTTPService actually uses URLLoader internally, so any URLLoader limitations are passed along to HTTPService. URLLoader's largest limitation is its inability to send any request with an HTTP method other than GET or POST. Note that these aren't the only limitations - there are many others, as well as some interesting quirks.

When confronted with these limitations, I considered the following workarounds:
  • FDS Server Proxy - This would require every HTTP request to hit the FDS server, followed by the target REST service.
  • Homegrown Server Proxy - This essentially would be a free alternative to FDS. The actual HTTP request sent by the client would have to have to be wrapped in an HTTP POST, and the POST would include information about the actual HTTP method desired. The legitimate HTTP Client on the server-side would then send the actual HTTP request with the appropriate method to the REST service.
  • Flash Socket API - This seemed like it had potential, however I had the added restriction of HTTPS communication with the REST service. Some third-party libraries such as as3crypto exist which have limited TLS 1.0 support, but the code was very new at the time, and I probably would have ended up writing a lot of HTTP client code.
  • Browser's native HTTP Client via XML HTTP Request + flash.external.ExternalInterface - Basically flash calls out to a javascript method which sends the actual HTTP request. The javascript function then calls back to flash when it receives the response. This is the option that seemed the least like a hack, and required the least amount of work. It's working rather nicely so far.

4 comments:

jeroen said...

do you have some example code for this?

How do you work around the domain issue? I though Javascript could only load data from the same domain..

nvihinen said...

Yes, the trade-off with the approach is that you can only make requests using the same protocol/host/port that the web page was loaded off of. This was not a problem in my case.

Unfortunately the code involved is mixed in with proprietary code, and I can't post it. But the code isn't that complicated. Basically one javascript method that gets called by ExternalInterface with a signature like this:

function sendHttpRequest(url, method, body, headers, requestId)

And a registered actionscript function that the javascript calls back that looks like this:

thisMovie("Main").sendHttpResponseToActionScript(
xmlHttpRequest.status, xmlHttpRequest.getAllResponseHeaders(), xmlHttpRequest.responseText, requestId);

jeroen said...

I think it's a pretty nice solution, most simple flex apps will connect to the same host anyway.

It's just weird that Adobe didn't include a decent HTTP client. We shouldn't have to work around this thing.

Anyways .. Thanks for your reply!

Anonymous said...

I agree with this post. With HttpService I can send an HTTP request to an URL with some header parameters set. But I can not send any content with the request whether it is GET or POST. This looks like a serious limitation of HttpService. Do developers in Adobe even realize it? Without this how can Adobe advertise flex to work with REST?

Again to restrict PUT, DELETE etc. to go through proxy services in FDS/BLAZEDS/LCDS is ridiculous. One of the comments in this blog shows how to make an HTTP PUT/DELETE request using the ExternalInterface.

- Indra