akifox-asynchttp

Haxe multi-platform Asynchronous HTTP+HTTPS Requests


Keywords
asynchronous, cpp, cross, flash, http, https, java, js, neko, request, response, synchronous
License
MIT
Install
haxelib install akifox-asynchttp 0.3.1

Documentation

akifox-asynchttp MIT License Haxe 3

Library Haxelib

BREAKING API VERSION 0.4

If you were using akifox-asynchttp, please check what have changed in the new version 0.4 and update your code as explained here

akifox-asynchttp (com.akifox.asynchttp.*)

HAXE Asynchronous HTTP Request library

The akifox-asynchttp library provides an easy-to-use tool to manage HTTP and HTTPS Requests in an pure Asynchronous way using multi-threading on available targets (Neko, CPP, Java), the flash.net.URLLoader on Flash target and haxe.Http on Javascript target.

Inspiration

I've taken inspiration to write the library from this snippet by Raivof https://gist.github.com/raivof/dcdb1d74f93d17132a1e

Thanks mate!

Table of Contents

Install and use with Haxe

You can easily install the library thru haxelib

haxelib install akifox-asynchttp

import it in your project files

import com.akifox.asynchttp.*;

compile with

-lib akifox-asynchttp

Use it in OpenFL Projects

After installing the library via Haxelib, add the library reference in your project.xml

<haxelib name="akifox-asynchttp" />

and finally you can import it in your project files

import com.akifox.asynchttp.*;

Features

  • Target support
    • Neko+CPP+Java: Socket with multi-threading
    • Flash: flash.net.URLLoader
    • Javascript: XmlHttpRequest
    • More platforms (php, python...)? Post a ticket if you would like one
  • HTTP Protocol Support
    • Request methods
      • Support for standard methods (GET, POST)
      • Support for restful methods (PUT, DELETE) (Javascript target unsupported)
      • Library accepts any method (HEAD, CONNECT, OPTIONS, TRACE, PATCH...) (Javascript target unsupported) [v0.4.7+]
    • Transfer modes
      • Support unknown transfer mode (HTTP/1.0+)
      • Support fixed content-length transfer mode (HTTP/1.0+)
      • Support chunked transfer mode (HTTP/1.1)
    • Redirects
      • Support redirect (Status 301,302,303,307)
      • Support relative urls [v0.4+]
      • Block 'infinite loops' + 'too many redirects (max: 10)' [v0.4+]
    • Choose if HTTP/1.0 or HTTP/1.1 [v0.4+]
    • HTTP over SSL (HTTPS) support [v0.4+]
    • Custom headers + custom user-agent [v0.4+]
    • Timeout on request [v0.3.1+]
  • Parsing
    • Json to Anonymous Structure
    • XML to Xml object
    • Image (Png,Jpeg, Gif) to BitmapData object (only with OpenFL support)
  • Additional features
    • Synchronous request option [v0.4+]
    • Progress callback [v0.4.3+]
    • Support SSL for iOS and Android [v0.4.4+]
  • Future releases
    • Posting content on request (it should work but needs extensive tests)
    • Chain requests (one thread multiple requests)
    • Test socket solution on Flash target (it could be better than URLLoader)

Important platform notes

CPP/NEKO/JAVA

  • Full support

FLASH:

  • response.isBinary is always TRUE on the response object
  • response.headers is always empty, so don't rely on response.contentType
  • you have to know what you are going to fetch to parse it as you need (toText(), toJson(), toXml()...)

JAVASCRIPT:

  • response.isBinary is always FALSE on the response object
  • response.headers is always empty, so don't rely on response.contentType
  • you have to know what you are going to fetch to parse it as you need (toText(), toJson(), toXml()...)
  • no support for methods other than POST and GET (limited by haxe.Http request)

Documentation

I strongly suggest to read the Quick Reference to understand how the class works, but if you need a complete documentation about all the library you can read the Online Documentation

Quick reference

Basic example

import com.akifox.asynchttp.*;

//[...]

// This is a basic GET example
var request = new HttpRequest({
         url : "http://www.google.com",
    callback : function(response:HttpResponse):Void {
                if (response.isOK) {
                  trace(response.content);
                  trace('DONE ${response.status}');
                } else {
                  trace('ERROR ${response.status} ${response.error}');
                }
              }  
});

request.send();

All the available variables exposed

import com.akifox.asynchttp.*;

// [...]

// NOTE:
// An HttpRequest is mutable until sent
// An HttpResponse is immutable

// Force log to console (default enabled on -debug)
AsyncHttp.logEnabled = true;

// Force error log to console (default enabled)
AsyncHttp.logErrorEnabled = true;

// Global custom user-agent header (default "akifox-asynchttp") [v0.4+]
AsyncHttp.userAgent = "akifox-asynchttp";

// Global maximum number of redirection allowed (default 10) [v0.4+]
AsyncHttp.maxRedirections = 10;

// This is a basic GET example that shows all the exposed variables
// NOTE: In FLASH and JAVASCRIPT cross-domain policies applies
//       Security errors and failed requests could happen
var request = new HttpRequest({

  // String | The request url (format is "protocol://host:port/resource?querystring")
  // NOTE: relative urls are accepted in FLASH and JAVASCRIPT
  url : "http://www.google.com",

  // Callback    The function that will handle the response
  callback : function(response:HttpResponse):Void {
         // NOTE: If callbackError is set the errors will be given to that function instead
         //       and response.isOK will be always True here
         if (response.isOK) {
           // A Good response
           // isOK == true if status is >= 200 and < 400

           // An unique ID that match the request.fingerprint
           var fingerprint:String = response.fingerprint;

           // The immutable request object relative to this response
           var request:HttpRequest = response.request;

           // Time elapsed from request start to response end
           var time:Float = response.time;

           // The URL fetched (after all HTTP 30x redirections)
           // (Usually it is the same as request.url)
           var url:String = response.urlString;

           // The guessued filename for the URL requested
           var filename:String = response.filename;

           // HTTP response headers
           // NOTE: You can use the following methods:
           //       .get('key'):String, .exists('key'):Bool, .keys():Iterator<String>
           // NOTE: Null in FLASH and JAVASCRIPT
           var headers:HttpHeaders = response.headers;

           // HTTP response status (set to 0 if connection error occurs)
           // NOTE: If callbackError is set the errors will be given to that function instead
           var status:Int = response.status;

           // The response content (String or Bytes)
           //       Based on content-type (XML, Json, Image [PNG, JPEG, GIF])
           // NOTE: Always Bytes in FLASH
           // NOTE: Always String in Javascript
           var content:Dynamic = response.content;

           // The response content untouched (Bytes)
           var contentRaw:Bytes = response.contentRaw;

           // The response content mime-type
           // NOTE: Always 'application/octet-stream' in FLASH
           // NOTE: Always 'text/plain' in JAVASCRIPT
           var contentType:String = response.contentType;

           // The response content length
           var contentLength:Int = response.contentLength;

           // Tells if the response.content is String or Byte
           // NOTE: Always true in FLASH
           // NOTE: Always false in JAVASCRIPT
           var isBinary:Bool = response.isBinary;
           var isText:Bool = response.isText; // == !isBinary

           // Tells if the response.content is Xml data
           // NOTE: Always false in FLASH and JAVASCRIPT
           var isXml:Bool = response.isXml; // == !isBinary

           // Tells if the response.content is Json data
           // NOTE: Always false in FLASH and JAVASCRIPT
           var isJson:Bool = response.isJson; // == !isBinary

           // Parse the content as Text [String]
           // Convert the data to String
           // (Usually is made in automatic, but using this
           //   function make sure it will be a String type)
           var contentText:String = response.toText();

           // Parse the content as Json
           //       [Anonymous Structure Object] (returns null on error)
           var contentJson:Dynamic = response.toJson();

           // Parse the content as Xml
           //       [Xml Object] (returns null on error)
           var contentXml:Xml = response.toXml();

           trace('DONE (HTTP STATUS ${response.status})');

         } else {

           // Any connection or status error
           trace('ERROR ${response.status} ${response.error})');

         }
      },

  // !OPTIONAL! If set this function will handle all the response errors
  //            otherwise success and failure responses will be given
  //            to the standard 'callback'
  callbackError : function(response:HttpResponse):Void {
         // response.isOK is always False here

         // HTTP response status
         // 0 if connection error
         // HTTP error status if connection is ok (<200 or >=400)
         var status:Int = response.status;

         trace('ERROR (HTTP STATUS ${status})');

      },

  // !OPTIONAL! If set this function will be called at every update on an HTTP Transfer
  // and at the beginning/end of the transfer
  // It gives back 2 values:
  //   loaded:Int loaded bytes
  //   total:Int total bytes (-1 if undefined)
  callbackProgress : function(loaded:Int,total:Int):Void {

         trace('LOADING ${loaded}/${total}');

      },

  // HttpMethod | The request http method
  // String (constants helper in HttpMethod class)
  // NOTE: Only GET and POST are supported in Javascript
  method : HttpMethod.GET,

  // HttpHeaders | Custom HTTP headers (default 'empty')
  // NOTE: Not supported on FLASH and JAVASCRIPT
  // NOTE: You CANNOT set the basic headers as the library manage them
  //       Ignored headers: "User-Agent","Host","Content-Type" and "Content-Length"
  headers : new HttpHeaders({
                  'Pragma':'no-cache',
                  'Accept-Language':'en-US'
                }),

  // Int     | Request timeout in seconds (default 10 seconds) [v0.3.1+]
  timeout : 10,

  // Bool    | Make the request asynchronous (default is true) [v0.4+]
  async : true,

  // Bool    | Use HTTP/1.1 otherwise 1.0 (default is true) [v0.4+]
  http11 : true,

  // Dynamic | The request content data to be sent
  content : null,

  // String  | The request content mime-type
  contentType : null // default "application/x-www-form-urlencoded"

}); //end HttpRequest instance

// String     | An unique ID to identify the request (generated)
var fingerprint:String =  request.fingerprint;

// You can also set or reset every property after the object creation
// NOTE: after being sent the request will be made as immutable
//       and the only way to change it would be cloning it ( request.clone() )
request.timeout = 20; // example to set the timeout to 20 seconds

request.send(); // start the request as set

// If you want to send the request again you have to clone it
// It will get a new fingerprint and you can change all its properties
// (This is because once a request is sent it gets finalised and it becomes immutable)
var newRequest = request.clone();
newRequest.timeout = 10; //change a property example
newRequest.send();

Examples

One example

Check it out

The example shows loading an wikipedia page (with redirect from http to https and so also SSL support).

Simple example with concurrent multiple requests

Check it out

The example shows how to handle multiple requests and responses

Interactive example

Check it out

The example allow the user to try any URL to see the behavior of the library with redirects, errors and his own urls.

Javascript example

Check it out

A simple example in javascript that shows how to use the library.

Flash example

Check it out

A simple example in flash that shows how to use the library.

Loader example

Check it out

A simple example to show the callbackProgress optional callback

OpenFL Image URL to Stage (Bitmap) example

Check it out

The example shows how to load a picture from an URL and display it on stage as Bitmap (The HAXE logo is loaded via HTTPS the other two images via HTTP)

It supports most of the targets (for sure neko, android and ios)

NOTE: This example works only with OpenFL because it supports decoding of images (Jpeg, PNG and GIF) from raw bytes data.

Also, you can use the library to load any kind of data, not just images, exactly like in the other examples.

Write to a file the response

If you want to write in a file the response content you can use this snippet.

It will handle binary file (i.e. Images, Zip...) or text file (i.e. Html, Xml, Json...)

NOTE: Take care of the path on different platforms!

request.callback = function(response:HttpResponse):Void {
                     var file = sys.io.File.write("/the/path/you/want/"+response.filename,response.contentIsBinary);
                     try {
                        file.write(response.contentRaw);
                        file.flush();
                     }
                        catch(err: Dynamic){
                        trace('Error writing file '+err);
                     }
                     file.close();
                   };