How to make URLLoader return an AsyncToken? - apache-flex

I was trying to retrieve binary data over HTTP for my Flex application, and was running into some stumbling blocks. HTTPService did not seem to deal with binary data well, people said to use URLLoader. But URLLoader does not have the nice AsyncToken/IResponder interface that HTTPService provides.
So, I did some searching and could not find anyone extending URLLoader to provide this kind of functionality. I went ahead and took a stab at it myself: http://pastebin.com/d7369d0e0
Basically it wraps a URLLoader and an AsyncToken, and maps the COMPLETE, IO_ERROR, and SECURITY_ERROR events from URLLoader to results/faults that get raised on the AsyncToken.
Basic usage:
var tidbitLoader:AsyncURLLoader = new AsyncURLLoader();
tidbitLoader.dataFormat = URLLoaderDataFormat.BINARY;
var asyncToken:AsyncToken = tidbitLoader.load(new URLRequest("http://localhost/SampleTidbit.swf"));
asyncToken.addResponder(this);
public function result(resultEvent:Object):void
{
trace("result");
}
public function fault(faultEvent:Object):void
{
var fault:FaultEvent = faultEvent as FaultEvent;
trace("fault: " + fault.toString());
}
Is this the right way to approach the problem? Are there existing solutions? I would love to hear feedback.
Thanks,
Karthik

Use the resultFormat = text on the HTTPService and then create a new ByteArray and call writeUTFBytes to write the text from the HTTPService result to the ByteArray. Then you should be able to set that ByteArray to a SWFLoader.source or call Loader.loadBytes.

I have tried your solution James with an AIR 1.5 app, but I get the following error when I set the ByteArray on my SWFLoader.source. Any ideas? I thought I read somewhere that AIR changes the HTTP headers and this may be the cause? Thanks Ben.
[DEBUG] mx.messaging.Channel 'direct_http_channel' channel sending message:
(mx.messaging.messages::HTTPRequestMessage)#0
body = (Object)#1
clientId = (null)
contentType = "application/x-www-form-urlencoded"
destination = "DefaultHTTP"
headers = (Object)#2
httpHeaders = (Object)#3
messageId = "3044E76C-CF0E-2D5F-96BE-74CFF62098B0"
method = "GET"
recordHeaders = false
timestamp = 0
timeToLive = 0
url = "http://www.myurl.com/test.jpg"
[INFO] mx.messaging.Producer '4FA2CCF4-2B3E-4EAB-2873-74CFF612AA72' producer connected.
[INFO] mx.messaging.Producer '4FA2CCF4-2B3E-4EAB-2873-74CFF612AA72' producer acknowledge of '3044E76C-CF0E-2D5F-96BE-74CFF62098B0'.
[INFO] mx.rpc.http.HTTPService Decoding HTTPService response
[DEBUG] mx.rpc.http.HTTPService Processing HTTPService response message:
(mx.messaging.messages::AcknowledgeMessage)#0
body = "ÿØÿà
Error #2044: Unhandled IOErrorEvent:. text=Error #2124: Loaded file is an unknown type.

Related

DataServiceContext.ExecuteAsync results in exception regarding the User-Agent header

I've created a Xamarin.Forms application and added a connected Odata Service.
Now when i try sending a request to the backend it will fail with the exception System.ArgumentException: The 'User-Agent' header must be modified using the appropriate property or method.
Parameter name: name.
What i've tried:
1: Handling the DataServiceContext_BuildingRequest and setting the header there using e.Headers["User-Agent"] = "xyz";
2: Setting the Content-Type header because i read in another thread somewhere that it helped (e.Headers.Add("Content-Type", "application/json"))
3: Setting the delegate of the DataServiceContext.Configurations.RequestPipeline.OnMessageCreating. The problem is the exception will be thrown as soon as i try to create a new instance of HttpWebRequestMessage passing in the args that it receives.
Pipeline delegate:
Configurations.RequestPipeline.OnMessageCreating = (args) =>
{
args.Headers["User-Agent"] = "xyz";
args.Headers.Add("Content-Type", "application/json");
args.Headers["Accept"] = "application/json";
var req = new HttpWebRequestMessage(args);
req.HttpWebRequest.ContentType = "application/json";
return req;
};
My suspicion regarding this is, that there was something changed in the underlying code that is used by the Odata HttpWebRequestMessage class which doesnt allow direct setting of the User-Agent header anymore.
Did anyone find a way around this?

Download Stream with RestSharp and ResponseWriter

I donwnload a stream with RestSharp by using the ResponseWriter.
var client = new RestClient
var request = new RestRequest();
// ...
request.ResponseWriter = (ms) => {
// how to detect the status code
};
var response = client.Execute(request);
How can I found out the HTTP Status Code in the ResponseWriter?
Is there a better way to download a Stream?
You can check response.StatusCode and response.StatusDescription after executing the request.
Interestingly, if you use the DownloadData method as described here https://github.com/restsharp/RestSharp/wiki/Other-Usage-Examples there is no way to access this information as far as I can tell.
Currently You can use property AdvancedResponseWriter instead ResponseWriter.
The main difference is that AdvancedResponseWriter in addition to Response Stream gets IHttpResponse and You can check Response Status.
It should be working properly from version 106.6.
https://github.com/restsharp/RestSharp/issues/1207

http streaming response unsupported message type: class org.jboss.netty.handler.stream.ChunkedStream

I am trying to write a netty based http server which takes text as input and returns an image as output. This image is generated on the fly based on the input text.
I copied the logic of org.jboss.netty.example.http.file.HttpStaticFileServerHandler into my own handler, and rather than writing a DefaultFileRegion as output in the channel,
final FileRegion region = new DefaultFileRegion(raf.getChannel(), 0, fileLength);
writeFuture = ch.write(region);
I am doing the following in my own handler:
InputStream imageIOStream = imageGenerator.generateImage(inputText);
ChannelFuture writeFuture = ch.write(new ChunkedStream(imageIOStream));
But I get the following exception on the server when I try to write back to the client.
java.lang.IllegalArgumentException: unsupported message type: class org.jboss.netty.handler.stream.ChunkedStream
at org.jboss.netty.channel.socket.nio.SocketSendBufferPool.acquire(SocketSendBufferPool.java:56)
at org.jboss.netty.channel.socket.nio.NioWorker.write0(NioWorker.java:463)
at org.jboss.netty.channel.socket.nio.NioWorker.writeFromUserCode(NioWorker.java:390)
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:137)
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:76)
at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:68)
at org.jboss.netty.channel.Channels.write(Channels.java:611)
at org.jboss.netty.channel.Channels.write(Channels.java:578)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:251)
Can someone please help me.
In your pipeline, have you setup the following?
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
See https://github.com/netty/netty/blob/master/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerPipelineFactory.java.

HttpService requestTimeout

How do I determine if the HttpService instance timed out? Thanks!
Be aware of this charming limitation of HTTPService ...
If you set the http.requestTimeout method, it will silently ignore the fact you asked it to be a POST request and discards any and all headers.
For some reason, in Flex, GET dumps all headers.
var http:HTTPService = new HTTPService()
http = new HTTPService();
http.method = "POST";
http.addEventListener(ResultEvent.RESULT, result*emphasized text*Handler);
http.addEventListener(FaultEvent.FAULT, resultHandler);
http.url = "http://www.example.com/post;
//http.requestTimeout = 5; //Watch out for this, there go the headers...
http.method = "POST";
http.send();
Oh yes, setting method = "POST" twice was intentional, what's even funnier is, if you run it in the debugger, when it comes to the last line, http.send(), and you look at the object's internal state, it's still set to be a POST request...
Muppets.
If you set requestTimeout then your request will raise a fault when it times out. So you can just add an event listener to the httpservice faultevent.
As of Flex 4.5 (possibly earlier) there's a specific fault code on the fault event for timeout errors:
In your fault handler:
if(faultEvent.fault.faultCode == "Client.Error.RequestTimeout"){
trace("TIMEOUT ERROR");
}

Prevent flex from caching an external resource

I'm writing a flex application that polls an xml file on the server to check for updated data every few seconds, and I'm having trouble preventing it from caching the data and failing to respond to it being updated.
I've attempted to set headers using the IIS control panel to use the following, without any luck:
CacheControl: no-cache
Pragma: no-cache
I've also attempted adding a random HTTP GET parameter to the end of the request URL, but that seems like it's stripped off by the HttpService class before the request is made. Here's the code to implement it:
http.url = "test.xml?time=" + new Date().getMilliseconds();
And here's the debug log that makes me think it failed:
(mx.messaging.messages::HTTPRequestMessage)#0
body = (Object)#1
clientId = (null)
contentType = "application/x-www-form-urlencoded"
destination = "DefaultHTTP"
headers = (Object)#2
httpHeaders = (Object)#3
messageId = "AAB04A17-8CB3-4175-7976-36C347B558BE"
method = "GET"
recordHeaders = false
timestamp = 0
timeToLive = 0
url = "test.xml"
Has anyone dealt with this problem?
The cache control HTTP header is "Cache-Control" ... note the hyphen! It should do the trick. If you leave out the hyphen, it is not likely to work.
I used the getTime() to make the date into a numeric string that did the trick. I also changed GET to POST. There were some issues with different file extensions being cached differently. For instance, a standard dynamic extension like .php or .jsp might not be cached by the browser and
private var myDate:Date = new Date();
[Bindable]
private var fileURLString:String = "http://www.mysite.com/data.txt?" + myDate.getTime();
Hopefully this helps someone.
I also threw a ton of the header parameters at it but they never fully did the trick. Examples:
// HTTPService called service
service.headers["Pragma"] = "no-cache"; // no caching of the file
service.headers["Cache-Control"] = "no-cache";

Resources