OpenLayers OpenLayers

Ticket #1652: http-2.patch

File http-2.patch, 41.6 kB (added by elemoine, 4 months ago)
  • tests/Protocol/HTTP.html

    old new  
     1<html> 
     2<head> 
     3  <script src="../../lib/OpenLayers.js"></script> 
     4  <script type="text/javascript"> 
     5 
     6    function test_constructor(t) { 
     7        t.plan(8); 
     8        var a = new OpenLayers.Protocol.HTTP({ 
     9            url: "foo" 
     10        }); 
     11 
     12        // 4 tests 
     13        t.eq(a.url, "foo", "constructor sets url"); 
     14        t.eq(a.options.url, a.url, "constructor copies url to options.url"); 
     15        t.eq(a.params, {}, "constructor sets params"); 
     16        t.eq(a.options.params, undefined, "constructor do not copy params to options.params"); 
     17 
     18        var params = {hello: "world"}; 
     19        var b = new OpenLayers.Protocol.HTTP({ 
     20            url: "bar", 
     21            params: params 
     22        }); 
     23 
     24        // 4 tests 
     25        t.eq(b.url, "bar", "constructor sets url"); 
     26        t.eq(b.options.url, b.url, "constructor copies url to options.url"); 
     27        t.eq(b.params, params, "constructor sets params"); 
     28        t.eq(b.options.params, b.params, "constructor copies params to options.params"); 
     29    } 
     30 
     31    function test_destroy(t) { 
     32        t.plan(3); 
     33        var protocol = new OpenLayers.Protocol.HTTP({ 
     34            url: "bar", 
     35            params: {hello: "world"} 
     36        }); 
     37        protocol.destroy(); 
     38        t.eq(protocol.options, null, "destroy nullifies options"); 
     39        t.eq(protocol.params, null, "destroy nullifies params"); 
     40        t.eq(protocol.headers, null, "destroy nullifies headers"); 
     41    } 
     42 
     43    function test_read(t) { 
     44        t.plan(10); 
     45        var protocol = new OpenLayers.Protocol.HTTP({ 
     46            'url': 'foo_url', 
     47            'params': {'k': 'foo_param'} 
     48        }); 
     49 
     50        // fake XHR request object 
     51        var request = {'status': 200}; 
     52 
     53        // options to pass to read 
     54        var readOptions = { 
     55            'url': 'bar_url', 
     56            'params': {'k': 'bar_param'}, 
     57            'headers': {'k': 'bar_header'}, 
     58            'scope': {'hello': 'world'}, 
     59            'callback': function() {} 
     60        }; 
     61 
     62        var response; 
     63 
     64        protocol.handleResponse = function(resp, opt) { 
     65            // 4 tests 
     66            var req = resp.priv; 
     67            t.ok(this == protocol, 
     68                'handleResponse called with correct scope'); 
     69            t.ok(opt == readOptions, 
     70                'handleResponse called with correct options'); 
     71            t.eq(resp.CLASS_NAME, 'OpenLayers.Protocol.Response', 
     72                'handleResponse called with a Response object'); 
     73            t.eq(req, request, 
     74                'handleResponse called with correct request'); 
     75 
     76            response = resp; 
     77        }; 
     78 
     79        var _get = OpenLayers.Request.GET; 
     80 
     81        OpenLayers.Request.GET = function(options) { 
     82            // 5 tests 
     83            t.eq(options.url, readOptions.url, 
     84                'GET called with correct url in options'); 
     85            t.eq(options.params['k'], readOptions.params['k'], 
     86                'GET called with correct params in options'); 
     87            t.eq(options.headers['k'], readOptions.headers['k'], 
     88                'GET called with correct headers in options'); 
     89            t.eq(options.scope, undefined, 
     90                'GET called with correct scope in options'); 
     91            t.ok(typeof options.callback == 'function', 
     92                'GET called with a callback in options'); 
     93            t.delay_call(0.1, function() { 
     94                options.callback(request); 
     95                t.ok(resp == response, 
     96                    'read returns the expected response object');         
     97                // cleanup 
     98                protocol.destroy(); 
     99                OpenLayers.Request.GET = _get; 
     100            }); 
     101            return request; 
     102        }; 
     103 
     104        var resp = protocol.read(readOptions); 
     105    } 
     106 
     107    function test_parseFeatures(t) { 
     108        t.plan(5); 
     109 
     110        var protocol = new OpenLayers.Protocol.HTTP(); 
     111 
     112        // test responseXML - 2 tests 
     113        var request = { 
     114            'responseXML': { 
     115                'documentElement': 'xml' 
     116            } 
     117        }; 
     118        protocol.format = { 
     119            'read': function(doc) { 
     120                t.eq(doc.documentElement, 'xml', 
     121                    'format.read called with correct doc'); 
     122                return doc.documentElement; 
     123            } 
     124        }; 
     125        var ret = protocol.parseFeatures(request); 
     126        t.eq(ret, 'xml', 'parseFeatures returns expected value'); 
     127 
     128        // test responseText - 2 tests 
     129        var request = { 
     130            'responseText': 'text' 
     131        }; 
     132        protocol.format = { 
     133            'read': function(doc) { 
     134                t.eq(doc, 'text', 
     135                    'format.read called with correct doc'); 
     136                return doc; 
     137            } 
     138        }; 
     139        var ret = protocol.parseFeatures(request); 
     140        t.eq(ret, 'text', 'parseFeatures returns expected value'); 
     141 
     142        // test empty responseText - 1 test 
     143        var request = { 
     144            'responseText': '' 
     145        }; 
     146        protocol.format = { 
     147            'read': function(doc) { 
     148                t.fail('format.read should not be called'); 
     149            } 
     150        }; 
     151        var ret = protocol.parseFeatures(request); 
     152        t.eq(ret, null, 'parseFeatures returns expected value'); 
     153    } 
     154 
     155    function test_create(t) { 
     156        t.plan(10); 
     157        var protocol = new OpenLayers.Protocol.HTTP({ 
     158            'url': 'foo_url', 
     159            'format': {'write': function() {}} 
     160        }); 
     161 
     162        // fake XHR request object 
     163        var request = {'status': 200}; 
     164 
     165        // features to pass to create 
     166        var features = ['feature']; 
     167 
     168        // options to pass to create 
     169        var createOptions = { 
     170            'url': 'bar_url', 
     171            'headers': {'k': 'bar_header'}, 
     172            'scope': {'hello': 'world'}, 
     173            'callback': function() {} 
     174        }; 
     175 
     176        var response; 
     177 
     178        protocol.handleCreate = function(resp, opt) { 
     179            // 5 tests 
     180            var req = resp.priv; 
     181            t.ok(this == protocol, 
     182                'handleCreate called with correct scope'); 
     183            t.ok(opt == createOptions, 
     184                'handleCreate called with correct options'); 
     185            t.eq(resp.CLASS_NAME, 'OpenLayers.Protocol.Response', 
     186                'handleCreate called with a Response object'); 
     187            t.ok(resp.reqFeatures == features, 
     188                'handleCreate called with correct requested features in response'); 
     189            t.eq(req, request, 
     190                'handleCreate called with correct request'); 
     191 
     192            response = resp; 
     193        }; 
     194 
     195        var _post = OpenLayers.Request.POST; 
     196 
     197        OpenLayers.Request.POST = function(options) { 
     198            // 4 tests 
     199            t.eq(options.url, createOptions.url, 
     200                'POST called with correct url in options'); 
     201            t.eq(options.headers['k'], createOptions.headers['k'], 
     202                'POST called with correct headers in options'); 
     203            t.eq(options.scope, undefined, 
     204                'POST called with correct scope in options'); 
     205            t.ok(typeof options.callback == 'function', 
     206                'POST called with a callback in options'); 
     207            // call callback - delayed because this function has to return first 
     208            t.delay_call(0.1, function() { 
     209                options.callback(request); 
     210                t.ok(resp == response, 
     211                    'create returns the expected response object'); 
     212                // cleanup 
     213                protocol.destroy(); 
     214                OpenLayers.Request.POST = _post; 
     215            }); 
     216            return request; 
     217        }; 
     218 
     219        var resp = protocol.create(features, createOptions); 
     220    } 
     221 
     222    function test_update(t) { 
     223        t.plan(10); 
     224        var protocol = new OpenLayers.Protocol.HTTP({ 
     225            'url': 'foo_url', 
     226            'format': {'write': function() {}} 
     227        }); 
     228 
     229        // fake XHR request object 
     230        var request = {'status': 200}; 
     231 
     232        // feature to pass to update 
     233        var feature = {'feature':'feature'}; 
     234 
     235        // options to pass to update 
     236        var updateOptions = { 
     237            'url': 'bar_url', 
     238            'headers': {'k': 'bar_header'}, 
     239            'scope': {'hello': 'world'}, 
     240            'callback': function() {} 
     241        }; 
     242 
     243        var response; 
     244 
     245        protocol.handleUpdate = function(resp, opt) { 
     246            var req = resp.priv; 
     247            // 5 tests 
     248            t.ok(this == protocol, 
     249                'handleUpdate called with correct scope'); 
     250            t.ok(opt == updateOptions, 
     251                'handleUpdate called with correct options'); 
     252            t.eq(resp.CLASS_NAME, 'OpenLayers.Protocol.Response', 
     253                'handleUpdate called with a Response object'); 
     254            t.ok(resp.reqFeatures == feature, 
     255                'handleUpdate called with correct requested feature in response'); 
     256            t.eq(req, request, 
     257                'handleUpdate called with correct request'); 
     258 
     259            response = resp; 
     260        }; 
     261 
     262        var _put = OpenLayers.Request.PUT; 
     263 
     264        OpenLayers.Request.PUT = function(options) { 
     265            // 4 tests 
     266            t.eq(options.url, updateOptions.url, 
     267                'PUT called with correct url in options'); 
     268            t.eq(options.headers['k'], updateOptions.headers['k'], 
     269                'PUT called with correct headers in options'); 
     270            t.eq(options.scope, undefined, 
     271                'PUT called with correct scope in options'); 
     272            t.ok(typeof options.callback == 'function', 
     273                'PUT called with a callback in options'); 
     274            // call callback - delayed because this function has to return first 
     275            t.delay_call(0.1, function() { 
     276                options.callback(request); 
     277                t.ok(resp == response, 
     278                    'update returns the expected response object'); 
     279                // cleanup 
     280                protocol.destroy(); 
     281                OpenLayers.Request.PUT = _put; 
     282            }); 
     283            return request; 
     284        }; 
     285 
     286        var resp = protocol.update(feature, updateOptions); 
     287 
     288    } 
     289    function test_handleResponse(t) { 
     290        t.plan(6); 
     291 
     292        var protocol = new OpenLayers.Protocol.HTTP(); 
     293 
     294        var options, response, request, features; 
     295 
     296        // test options - 2 tests 
     297        var scope = {'fake': 'scope'}; 
     298        options = { 
     299            'scope': scope, 
     300            'callback': function(resp) { 
     301                t.ok(this == scope, 
     302                    '[no status] callback called with correct scope'); 
     303                t.ok(resp == response, 
     304                    '[no status] callback called with correct response'); 
     305            } 
     306        }; 
     307        response = {priv: {}}; 
     308        protocol.handleResponse(response, options); 
     309         
     310        // test failure condition - 1 test 
     311        options = { 
     312            'callback': function(resp) { 
     313                t.eq(resp.code, OpenLayers.Protocol.Response.FAILURE, 
     314                    '[status 400] callback called with correct response code'); 
     315            } 
     316        }; 
     317        response = {priv: {status: 400}}; 
     318        protocol.handleResponse(response, options); 
     319 
     320        // test success condition - 3 tests 
     321        features = {'fake': 'features'}; 
     322        options = { 
     323            'callback': function(resp) { 
     324                t.eq(resp.code, OpenLayers.Protocol.Response.SUCCESS, 
     325                    '[status 200] callback called with correct response code'); 
     326                t.eq(resp.features, features, 
     327                    '[status 200] callback called with correct features in response'); 
     328            } 
     329        }; 
     330        response = {priv: {status: 200}}; 
     331        protocol.parseFeatures = function(request) { 
     332            t.ok(request == response.priv, 
     333                '[status 200] parseFeatures called with correct request'); 
     334            return features; 
     335        } 
     336        protocol.handleResponse(response, options); 
     337 
     338        // cleanup 
     339        protocol.destroy(); 
     340    } 
     341 
     342    function test_delete(t) { 
     343        t.plan(10); 
     344        var protocol = new OpenLayers.Protocol.HTTP({ 
     345            'url': 'foo_url' 
     346        }); 
     347 
     348        // fake XHR request object 
     349        var request = {'status': 200}; 
     350 
     351        // feature to pass to delete 
     352        var feature = {'url': 'bar_url'}; 
     353 
     354        // options to pass to delete 
     355        var deleteOptions = { 
     356            'url': 'bar_url', 
     357            'headers': {'k': 'bar_header'}, 
     358            'scope': {'hello': 'world'}, 
     359            'callback': function() {} 
     360        }; 
     361 
     362        var response; 
     363 
     364        protocol.handleDelete = function(resp, opt) { 
     365            // 5 tests 
     366            var req = resp.priv; 
     367            t.ok(this == protocol, 
     368                'handleDelete called with correct scope'); 
     369            t.ok(opt == deleteOptions, 
     370                'handleDelete called with correct options'); 
     371            t.eq(resp.CLASS_NAME, 'OpenLayers.Protocol.Response', 
     372                'handleDelete called with a Response object'); 
     373            t.ok(resp.reqFeatures == feature, 
     374                'handleDelete called with correct requested feature in response'); 
     375            t.eq(req, request, 
     376                'handleDelete called with correct request'); 
     377 
     378            response = resp; 
     379        }; 
     380 
     381        var _delete = OpenLayers.Request.DELETE; 
     382 
     383        OpenLayers.Request.DELETE = function(options) { 
     384            // 4 tests 
     385            t.eq(options.url, deleteOptions.url, 
     386                'DELETE called with correct url in options'); 
     387            t.eq(options.headers['k'], deleteOptions.headers['k'], 
     388                'DELETE called with correct headers in options'); 
     389            t.eq(options.scope, undefined, 
     390                'DELETE called with correct scope in options'); 
     391            t.ok(typeof options.callback == 'function', 
     392                'DELETE called with a callback in options'); 
     393            // call callback - delayed because this function has to return first 
     394            t.delay_call(0.1, function() { 
     395                options.callback(request); 
     396                t.ok(resp == response, 
     397                    'read returns the expected response object'); 
     398                // cleanup 
     399                protocol.destroy(); 
     400                OpenLayers.Request.DELETE = _delete; 
     401            }); 
     402            return request; 
     403        }; 
     404 
     405        var resp = protocol['delete'](feature, deleteOptions); 
     406 
     407    } 
     408 
     409    function test_handleDelete(t) { 
     410        t.plan(4); 
     411 
     412        var protocol = new OpenLayers.Protocol.HTTP(); 
     413 
     414        var options, response, request, features; 
     415 
     416        // test options - 2 tests 
     417        var scope = {'fake': 'scope'}; 
     418        options = { 
     419            'scope': scope, 
     420            'callback': function(resp) { 
     421                t.ok(this == scope, 
     422                    'callback called with correct scope'); 
     423                t.ok(resp == response, 
     424                    'callback called with correct response'); 
     425            } 
     426        }; 
     427        response = {priv: {}}; 
     428        protocol.handleDelete(response, options); 
     429         
     430        // test failure condition - 1 test 
     431        options = { 
     432            'callback': function(resp) { 
     433                t.eq(resp.code, OpenLayers.Protocol.Response.FAILURE, 
     434                    'callback called with correct response code'); 
     435            } 
     436        }; 
     437        response = {priv: {status: 400}}; 
     438        protocol.handleDelete(response, options); 
     439 
     440        // test success condition - 1 test 
     441        options = { 
     442            'callback': function(resp) { 
     443                t.eq(resp.code, OpenLayers.Protocol.Response.SUCCESS, 
     444                    'callback called with correct response code'); 
     445            } 
     446        }; 
     447        response = {priv: {status: 200}}; 
     448        protocol.handleDelete(response, options); 
     449 
     450        // cleanup 
     451        protocol.destroy(); 
     452    } 
     453 
     454    function test_commit(t) { 
     455        t.plan(17); 
     456 
     457        var protocol = new OpenLayers.Protocol.HTTP(); 
     458 
     459        // 6 features 
     460        var features = [ 
     461            {'state': OpenLayers.State.INSERT}, 
     462            {'state': OpenLayers.State.INSERT}, 
     463            {'state': OpenLayers.State.UPDATE}, 
     464            {'state': OpenLayers.State.UPDATE}, 
     465            {'state': OpenLayers.State.DELETE}, 
     466            {'state': OpenLayers.State.DELETE} 
     467        ]; 
     468 
     469        var options = { 
     470            'create': { 
     471                'callback': function(resp) { 
     472                } 
     473            }, 
     474            'update': { 
     475                'callback': function(resp) { 
     476                } 
     477            }, 
     478            'delete': { 
     479                'callback': function(resp) { 
     480                } 
     481            } 
     482        }; 
     483 
     484        var respCreate = new OpenLayers.Protocol.Response(); 
     485        var respUpdate = new OpenLayers.Protocol.Response(); 
     486        var respDelete = new OpenLayers.Protocol.Response(); 
     487 
     488        // 2 tests 
     489        protocol['create'] = function(feature, options) { 
     490            t.ok(options.scope == protocol, 
     491                'create called with correct scope'); 
     492            t.ok(typeof options.callback == 'function', 
     493                'create called with a callback in options'); 
     494            options.callback.call(options.scope, respCreate); 
     495            return respCreate; 
     496        }; 
     497        // 4 tests 
     498        protocol['update'] = function(feature, options) { 
     499            t.ok(options.scope == protocol, 
     500                'update called with correct scope'); 
     501            t.ok(typeof options.callback == 'function', 
     502                'update called with a callback in options'); 
     503            options.callback.call(options.scope, respUpdate); 
     504            return respUpdate; 
     505        }; 
     506        // 4 tests 
     507        protocol['delete'] = function(feature, options) { 
     508            t.ok(options.scope == protocol, 
     509                'delete called with correct scope'); 
     510            t.ok(typeof options.callback == 'function', 
     511                'delete called with a callback in options'); 
     512            options.callback.call(options.scope, respDelete); 
     513            return respDelete; 
     514        }; 
     515 
     516        var count = 0; 
     517 
     518        // 5 tests 
     519        protocol.callUserCallback = function(resp, opt) { 
     520            t.ok(opt == options, 
     521                'callUserCallback called with correction options map'); 
     522            count++; 
     523        }; 
     524 
     525        var resp = protocol.commit(features, options); 
     526 
     527        // 2 tests 
     528        t.eq(count, 5, 'callUserCallback called for each request'); 
     529        t.eq(resp.length, 5, 'commit returns array with correct length'); 
     530 
     531        // cleanup 
     532        protocol.destroy(); 
     533    } 
     534 
     535    function test_callUserCallback(t) { 
     536        t.plan(6); 
     537 
     538        var protocol = new OpenLayers.Protocol.HTTP(); 
     539 
     540        var options, resp; 
     541        var scope = {'fake': 'scope'}; 
     542 
     543        // test commit callback 
     544        // 1 tests 
     545        options = { 
     546            'callback': function() { 
     547                t.ok(this == scope, 'callback called with correct scope'); 
     548            }, 
     549            'scope': scope 
     550        }; 
     551        resp = {'requestType': 'create', 'last': true}; 
     552        protocol.callUserCallback(resp, options); 
     553        // 0 test 
     554        resp = {'requestType': 'create', 'last': false}; 
     555        protocol.callUserCallback(resp, options); 
     556 
     557        // test create callback 
     558        // 2 tests 
     559        options = { 
     560            'create': { 
     561                'callback': function(r) { 
     562                    t.ok(this == scope, 'callback called with correct scope'); 
     563                    t.ok(r == resp, 'callback called with correct response'); 
     564                }, 
     565                'scope': scope 
     566            } 
     567        }; 
     568        resp = {'requestType': 'create'}; 
     569        protocol.callUserCallback(resp, options); 
     570 
     571        // test with both callbacks set 
     572        // 3 tests 
     573        options = { 
     574            'create': { 
     575                'callback': function(r) { 
     576                    t.ok(this == scope, 'callback called with correct scope'); 
     577                    t.ok(r == resp, 'callback called with correct response'); 
     578                }, 
     579                'scope': scope 
     580            }, 
     581            'callback': function() { 
     582                t.ok(this == scope, 'callback called with correct scope'); 
     583            }, 
     584            'scope': scope 
     585        }; 
     586        resp = {'requestType': 'create', 'last': true}; 
     587        protocol.callUserCallback(resp, options); 
     588 
     589        // no callback set 
     590        // 0 test 
     591        options = { 
     592            'delete': { 
     593                'callback': function(resp) { 
     594                    t.fail('callback should not get called'); 
     595                } 
     596            } 
     597        }; 
     598        resp = {'requestType': 'create'}; 
     599        protocol.callUserCallback(resp, options); 
     600 
     601        // cleanup 
     602        protocol.destroy(); 
     603    } 
     604 
     605    function test_options(t) { 
     606        t.plan(7); 
     607 
     608        var _R = OpenLayers.Protocol.Response; 
     609        OpenLayers.Protocol.Response = function() { 
     610            this.priv = {status: 200}; 
     611        }; 
     612 
     613        // test that read with no options uses protocol options - 5 tests 
     614        var url = "foo"; 
     615        var headers = {}; 
     616        var params = {}; 
     617        var scope = {}; 
     618        var protocol = new OpenLayers.Protocol.HTTP({ 
     619            format: new OpenLayers.Format({read: function(){}, write: function(){}}), 
     620            url: url, 
     621            headers: headers, 
     622            params: params, 
     623            callback: function() { 
     624                t.ok(true, "[read] Correct callback."); 
     625                t.eq(this, scope, "[read] Correct scope."); 
     626            }, 
     627            scope: scope 
     628        });         
     629        var _issue = OpenLayers.Request.issue; 
     630        OpenLayers.Request.issue = function(config) { 
     631            t.eq(config.url, url, "[" + config.method + "] Correct url."); 
     632            t.eq(config.headers, headers, "[" + config.method + "] Correct headers."); 
     633            t.eq(config.params, params, "[" + config.method + "] Correct params."); 
     634            config.callback.call(config.scope); 
     635        }; 
     636        protocol.read(); 
     637        OpenLayers.Request.issue = _issue; 
     638 
     639        // test that commit with no options uses protocol options - 2 tests 
     640        _issue = OpenLayers.Request.issue; 
     641        OpenLayers.Request.issue = function(config) { 
     642            config.callback.call(config.scope); 
     643        }; 
     644        var called = 0; 
     645        protocol.options.callback = function() { 
     646            called++; 
     647            t.eq(this, scope, "[commit] Correct scope."); 
     648        }; 
     649        protocol.commit([ 
     650            {state: OpenLayers.State.INSERT}, 
     651            {state: OpenLayers.State.INSERT}, 
     652            {state: OpenLayers.State.UPDATE}, 
     653            {state: OpenLayers.State.UPDATE}, 
     654            {state: OpenLayers.State.DELETE}, 
     655            {state: OpenLayers.State.DELETE} 
     656        ]); 
     657        t.eq(called, 1, "[commit] Callback called once."); 
     658 
     659        // cleanup 
     660        protocol.destroy(); 
     661        OpenLayers.Protocol.Response = _R; 
     662    } 
     663 
     664 
     665  </script> 
     666</head> 
     667<body> 
     668</body> 
     669</html> 
  • tests/list-tests.html

    old new  
    113113    <li>Popup/FramedCloud.html</li> 
    114114    <li>Projection.html</li> 
    115115    <li>Protocol.html</li> 
     116    <li>Protocol/HTTP.html</li> 
    116117    <li>Renderer.html</li> 
    117118    <li>Renderer/Canvas.html</li> 
    118119    <li>Renderer/Elements.html</li> 
  • lib/OpenLayers/Protocol/HTTP.js

    old new  
     1/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD 
     2 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the 
     3 * full text of the license. */ 
     4 
     5/** 
     6 * @requires OpenLayers/Protocol.js 
     7 * @requires OpenLayers/Feature/Vector.js 
     8 */ 
     9 
     10/** 
     11 * Class: OpenLayers.Protocol.HTTP 
     12 * A basic HTTP protocol for vector layers.  Create a new instance with the 
     13 *     <OpenLayers.Protocol.HTTP> constructor. 
     14 * 
     15 * Inherits from: 
     16 *  - <OpenLayers.Protocol> 
     17 */ 
     18OpenLayers.Protocol.HTTP = OpenLayers.Class(OpenLayers.Protocol, { 
     19 
     20    /** 
     21     * Property: url 
     22     * {String} - Service URL, read-only, set through the options 
     23     *     passed to constructor. 
     24     */ 
     25    url: null, 
     26 
     27    /** 
     28     * Property: headers 
     29     * {Object} - HTTP request headers, read-only, set through the options 
     30     *     passed to the constructor, 
     31     *     Example: {'Content-Type': 'plain/text'} 
     32     */ 
     33    headers: null, 
     34 
     35    /** 
     36     * Property: params 
     37     * {Object} - Parameters of GET requests, read-only, set through the options 
     38     *     passed to the constructor, 
     39     *     Example: {'bbox': '5,5,5,5'} 
     40     */ 
     41    params: null, 
     42     
     43    /** 
     44     * Property: format 
     45     * {<OpenLayers.Format>} Parser for reading and writing features. 
     46     */ 
     47    format: null, 
     48 
     49    /** 
     50     * Property: callback 
     51     * {Object} - Function to be called when the <read>, <create>, 
     52     *     <update>, <delete> or <commit> operation completes, read-only, 
     53     *     set through the options passed to the constructor. 
     54     */ 
     55    callback: null, 
     56 
     57    /** 
     58     * Property: scope 
     59     * {Object} - Callback execution scope, read-only, set through the 
     60     *     options passed to the constructor. 
     61     */ 
     62    scope: null, 
     63 
     64    /** 
     65     * Constructor: OpenLayers.Protocol.HTTP 
     66     * A class for giving layers generic HTTP protocol. 
     67     * 
     68     * Parameters: 
     69     * options - {Object} Optional object whose properties will be set on the 
     70     *     instance. 
     71     * 
     72     * Valid options include: 
     73     * url - {String} 
     74     * headers - {Object}  
     75     * params - {Object} 
     76     * format - {<OpenLayers.Format>} 
     77     * callback - {Function} 
     78     * scope - {Object} 
     79     */ 
     80    initialize: function(options) { 
     81        this.params = {}; 
     82        this.headers = {}; 
     83        OpenLayers.Protocol.prototype.initialize.apply(this, arguments); 
     84    }, 
     85     
     86    /** 
     87     * APIMethod: destroy 
     88     * Clean up the protocol. 
     89     */ 
     90    destroy: function() { 
     91        this.params = null; 
     92        this.headers = null; 
     93        OpenLayers.Protocol.prototype.destroy.apply(this); 
     94    }, 
     95    
     96    /** 
     97     * Method: createCallback 
     98     * Returns a function that applies the given public method with resp and 
     99     *     options arguments. 
     100     * 
     101     * Parameters: 
     102     * method - {Function} The method to be applied by the callback. 
     103     * response - {<OpenLayers.Protocol.Response>} The protocol response object. 
     104     * options - {Object} Options sent to the protocol method (read, create, 
     105     *     update, or delete). 
     106     */ 
     107    createCallback: function(method, response, options) { 
     108        return OpenLayers.Function.bind(function() { 
     109            method.apply(this, [response, options]); 
     110        }, this); 
     111    }, 
     112 
     113    /** 
     114     * Method: read 
     115     * Construct a request for reading new features. 
     116     * 
     117     * Parameters: 
     118     * options - {Object} Optional object for configuring the request. 
     119     *     This object is modified and should not be reused. 
     120     * 
     121     * Returns: 
     122     * {<OpenLayers.Protocol.Response>} A response object, whose "priv" property 
     123     *     references the HTTP request, this object is also passed to the 
     124     *     callback function when the request completes, its "features" property 
     125     *     is then populated with the the features received from the server. 
     126     */ 
     127    read: function(options) { 
     128        options = OpenLayers.Util.applyDefaults(options, this.options); 
     129        var resp = new OpenLayers.Protocol.Response({requestType: "read"}); 
     130 
     131        resp.priv = OpenLayers.Request.GET({ 
     132            url: options.url, 
     133            callback: this.createCallback(this.handleRead, resp, options), 
     134            params: options.params, 
     135            headers: options.headers 
     136        });         
     137 
     138        return resp; 
     139    }, 
     140 
     141    /** 
     142     * Method: handleRead 
     143     * Individual callbacks are created for read, create and update, should 
     144     *     a subclass need to override each one separately. 
     145     * 
     146     * Parameters: 
     147     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to 
     148     *     the user callback. 
     149     * options - {Object} The user options passed to the read call. 
     150     */ 
     151    handleRead: function(resp, options) { 
     152        this.handleResponse(resp, options); 
     153    }, 
     154     
     155    /** 
     156     * Method: create 
     157     * Construct a request for writing newly created features. 
     158     * 
     159     * Parameters: 
     160     * features - {Array({<OpenLayers.Feature.Vector>})} or 
     161     *     {<OpenLayers.Feature.Vector>} 
     162     * options - {Object} Optional object for configuring the request. 
     163     *     This object is modified and should not be reused. 
     164     * 
     165     * Returns: 
     166     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 
     167     *     object, whose "priv" property references the HTTP request, this  
     168     *     object is also passed to the callback function when the request 
     169     *     completes, its "features" property is then populated with the 
     170     *     the features received from the server. 
     171     */ 
     172    create: function(features, options) { 
     173        options = OpenLayers.Util.applyDefaults(options, this.options); 
     174 
     175        var resp = new OpenLayers.Protocol.Response({ 
     176            reqFeatures: features, 
     177            requestType: "create" 
     178        }); 
     179 
     180        resp.priv = OpenLayers.Request.POST({ 
     181            url: options.url, 
     182            callback: this.createCallback(this.handleCreate, resp, options), 
     183            headers: options.headers, 
     184            data: this.format.write(features) 
     185        }); 
     186 
     187        return resp; 
     188    }, 
     189 
     190    /** 
     191     * Method: handleCreate 
     192     * Called the the request issued by <create> is complete.  May be overridden 
     193     *     by subclasses. 
     194     * 
     195     * Parameters: 
     196     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to 
     197     *     any user callback. 
     198     * options - {Object} The user options passed to the create call. 
     199     */ 
     200    handleCreate: function(resp, options) { 
     201        this.handleResponse(resp, options); 
     202    }, 
     203 
     204    /** 
     205     * Method: update 
     206     * Construct a request updating modified feature. 
     207     * 
     208     * Parameters: 
     209     * feature - {<OpenLayers.Feature.Vector>} 
     210     * options - {Object} Optional object for configuring the request. 
     211     *     This object is modified and should not be reused. 
     212     * 
     213     * Returns: 
     214     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 
     215     *     object, whose "priv" property references the HTTP request, this  
     216     *     object is also passed to the callback function when the request 
     217     *     completes, its "features" property is then populated with the 
     218     *     the feature received from the server. 
     219     */ 
     220    update: function(feature, options) { 
     221        var url = options.url || feature.url || this.options.url; 
     222        options = OpenLayers.Util.applyDefaults(options, this.options); 
     223 
     224        var resp = new OpenLayers.Protocol.Response({ 
     225            reqFeatures: feature, 
     226            requestType: "update" 
     227        }); 
     228 
     229        resp.priv = OpenLayers.Request.PUT({ 
     230            url: url, 
     231            callback: this.createCallback(this.handleUpdate, resp, options), 
     232            headers: options.headers, 
     233            data: this.format.write(feature) 
     234        }); 
     235 
     236        return resp; 
     237    }, 
     238 
     239    /** 
     240     * Method: handleUpdate 
     241     * Called the the request issued by <update> is complete.  May be overridden 
     242     *     by subclasses. 
     243     * 
     244     * Parameters: 
     245     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to 
     246     *     any user callback. 
     247     * options - {Object} The user options passed to the update call. 
     248     */ 
     249    handleUpdate: function(resp, options) { 
     250        this.handleResponse(resp, options); 
     251    }, 
     252 
     253    /** 
     254     * Method: delete 
     255     * Construct a request deleting a removed feature. 
     256     * 
     257     * Parameters: 
     258     * feature - {<OpenLayers.Feature.Vector>} 
     259     * options - {Object} Optional object for configuring the request. 
     260     *     This object is modified and should not be reused. 
     261     * 
     262     * Returns: 
     263     * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response> 
     264     *     object, whose "priv" property references the HTTP request, this  
     265     *     object is also passed to the callback function when the request 
     266     *     completes. 
     267     */ 
     268    "delete": function(feature, options) { 
     269        var url = options.url || feature.url || this.options.url; 
     270        options = OpenLayers.Util.applyDefaults(options, this.options); 
     271 
     272        var resp = new OpenLayers.Protocol.Response({ 
     273            reqFeatures: feature, 
     274            requestType: "delete" 
     275        }); 
     276 
     277        resp.priv = OpenLayers.Request.DELETE({ 
     278            url: url, 
     279            callback: this.createCallback(this.handleDelete, resp, options), 
     280            headers: options.headers 
     281        }); 
     282 
     283        return resp; 
     284    }, 
     285 
     286    /** 
     287     * Method: handleDelete 
     288     * Called the the request issued by <delete> is complete.  May be overridden 
     289     *     by subclasses. 
     290     * 
     291     * Parameters: 
     292     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to 
     293     *     any user callback. 
     294     * options - {Object} The user options passed to the delete call. 
     295     */ 
     296    handleDelete: function(resp, options) { 
     297        this.handleResponse(resp, options); 
     298    }, 
     299 
     300    /** 
     301     * Method: handleResponse 
     302     * Called by CRUD specific handlers. 
     303     * 
     304     * Parameters: 
     305     * resp - {<OpenLayers.Protocol.Response>} The response object to pass to 
     306     *     any user callback. 
     307     * options - {Object} The user options passed to the create, read, update, 
     308     *     or delete call. 
     309     */ 
     310    handleResponse: function(resp, options) { 
     311        var request = resp.priv; 
     312        if(options.callback) { 
     313            if(request.status >= 200 && request.status < 300) { 
     314                // success 
     315                if(resp.requestType != "delete") { 
     316                    resp.features = this.parseFeatures(request); 
     317                } 
     318                resp.code = OpenLayers.Protocol.Response.SUCCESS; 
     319            } else { 
     320                // failure 
     321                resp.code = OpenLayers.Protocol.Response.FAILURE; 
     322            } 
     323            options.callback.call(options.scope, resp); 
     324        } 
     325    }, 
     326 
     327    /** 
     328     * Method: parseFeatures 
     329     * Read HTTP response body and return features. 
     330