Nickolay - HTTP.Request.Provider-0.01

Documentation | Source
Class('HTTP.Request.Provider', {
    
    trait        : 'JooseX.CPS',
    
    
    has : {
        method          : 'GET',
        
        user            : null,
        password        : null,
        
        url             : null,
        
        query           : null,
        data            : null,
        
        headers         : { is : 'rw' }
    },
    
    
    methods : {
        
        initialize : function () {
            var url     = this.url
            
            if (url) return this.request(url)
        }
    },
    
    
    continued : {
        
        methods : {
            
            request : function (url) {
                throw "Abstract method `request` of the 'HTTP.Request.Provider' reached"
            }
        }
    },
    
    
    my : {
        
        methods : {
        
            getRequest : function (config) {
                
                var providerClass = Joose.is_NodeJS ? HTTP.Request.Provider.NodeJS : HTTP.Request.Provider.XHR
                
                return new providerClass(config)
            }
        }
    }
});
Class('HTTP.Request.Provider.XHR', {
    
    isa        : 'HTTP.Request.Provider',
    
    
    has     : {
        transport : {
            is          : 'rw',
            builder     : 'this.buildTransport'
        }
    },
    
    
    methods : {
        
        buildTransport  : function () {
            if (window.XMLHttpRequest)
                return new XMLHttpRequest()
            else
                return new ActiveXObject("Microsoft.XMLHTTP")
        },
        
        
        urlEncode : function (object) {
            if (typeof object == 'string') return object
            
            if (typeof object == 'object') {
                var queryStr = ''
                
                Joose.O.each(object, function (value, name) {
                    if (queryStr) queryStr += '&'
                    
                    queryStr += encodeURIComponent(name) + '=' + encodeURIComponent(value + '')
                })
                
                return queryStr
            }
            
            return ''
        }
    },
    
    
    continued : {
        
        methods : {
            
            request : function (url) {
                var me          = this
                var CONT        = this.CONT
                var method      = this.method
                
                
                var query       = this.query
                
                if (query) {
                    var encodedQuery = this.urlEncode(query)
                    
                    if (url.match(/\?/))
                        url += '&' + encodedQuery
                    else
                        url += '?' + encodedQuery 
                }
                
                
                var xhr         = this.getTransport()
                
                xhr.open(method, url, true, this.user, this.password)
                
                
                
                var headers     = this.headers
                
                if (headers) Joose.O.eachOwn(headers, function (value, name) {
                    xhr.setRequestHeader(name, value)
                })
                
                
                var data = this.data
                
                if (typeof data == 'object') {
//                    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
                    
                    data = this.urlEncode(data) 
                }
                
                                
                xhr.onreadystatechange = function () {
                    var status = xhr.status
                    
                    if (xhr.readyState == 4)
                        if (status >= 200 && status < 300) 
                            CONT.CONTINUE({
                                status          : status,
                                text            : xhr.responseText,
                                request         : me
                            })
                        else 
                            CONT.THROW({
                                status          : status,
                                text            : xhr.responseText,
                                request         : me
                            })
                }
                
                xhr.send(data || null)
            }
        }
    }

})
;
Class('HTTP.Request.Provider.NodeJS', {
    
    isa        : 'HTTP.Request.Provider',
    
    
    continued : {
        
        methods : {
            
            request : function (url) {
                var QueryString = require('querystring')
                var CONT        = this.CONT
                
                var parsedURL       = require('url').parse(url)
                parsedURL.pathname  = parsedURL.pathname || '/index.html'
                
                // preparing query part of the URL
                var query       = this.query
                var queryStr    = parsedURL.query || ''
                
                if (typeof query == 'string') queryStr += query
                if (typeof query == 'object') queryStr += (queryStr ? '&' : '') + QueryString.stringify(query)
                
                var requestPath = parsedURL.pathname + (queryStr ? '?' + queryStr : '')
                
                
                var method      = this.method
                var data        = this.data
                var headers     = this.headers || {}
                
                if (data && typeof data == 'object') data = QueryString.stringify(data)
                
                if (!headers.host) {
                    headers.host = parsedURL.hostname
                    
                    if (parsedURL.port) headers.host += ':' + parsedURL.port
                }
                
                if (data) headers[ 'Content-Length' ] = data.length
                
                
                // making the actual request 
                
                var client      = require('http').createClient(parsedURL.port || 80, parsedURL.hostname)
                var request     = client.request(method, requestPath, headers)

                if (data) request.write(data, 'utf8')
                

                request.addListener('response', function (response) {
                    var status          = response.statusCode
                    var buffer          = ''
                    
                    response.setEncoding('utf8')
                    
                    response.addListener('data', function (chunk) {
                        buffer += chunk || ''
                    })
                    
                    response.addListener('end', function () {
                        
                        if (status >= 200 && status < 300)
                            CONT.CONTINUE({
                                status          : status,
                                text            : buffer
                            })
                        else 
                            CONT.THROW({
                                status          : status,
                                text            : buffer
                            })
                    })
                })
                
                request.end()
            }
        }
    }

})
;