source: Dev/trunk/src/server/util/http-result.js @ 527

Last change on this file since 527 was 527, checked in by hendrikvanantwerpen, 11 years ago
  • Dropped request module for a simple one we wrote ourselves using the native Node modules. Hopefully this one will not suffer from the problem that sometimes empty bodies are returned even when the statuscode and content-length of the request are ok & present.
  • Handle exceptions better in HTTPResult chain, they were hoisted in unknown responses before. Should we not include them in default processing, because they are special?
File size: 3.5 KB
Line 
1var _ = require('underscore')
2  ;
3
4var when;
5
6// type Callback = status:Number -> result:Any -> Either HTTPResult Any
7// type Handler = { f:Callback, next:HTTPResult }
8
9// <init> :: status:Number? -> result:Any? -> HTTPResult
10var counter = 0;
11function HTTPResult(status,result) {
12    this.id = counter++;
13    this.status = 0;
14    this.result = null;
15    this._handlers = [];
16    if ( status ) {
17        this.set(status,result);
18    }
19}
20
21// isSet :: Bool
22HTTPResult.prototype.isSet = function() {
23    return this.status !== 0;
24};
25
26// set :: status:Number -> result:Any? -> ()
27HTTPResult.prototype.set = function(status,result) {
28    if ( this.isSet() ) {
29        throw new Error("Result was already set.");
30    }
31    if ( !_.isNumber(status) ) {
32        throw new Error("Status must be a number.");
33    }
34    this.status = status;
35    this.result = result;
36    _.each(this._handlers,this._fire.bind(this));
37};
38
39// _fire :: Handler -> ()
40HTTPResult.prototype._fire = function(handler) {
41    try {
42        var ret = handler.f(this.status,this.result);
43        if ( ret instanceof HTTPResult ) {
44            ret.handle(handler.next.set.bind(handler.next));
45        } else {
46            handler.next.set(this.status,ret);
47        }
48    } catch(ex) {
49        console.log('HTTPResult','exception',ex.toString(),ex.stack);
50        handler.next.set(-1,ex);
51    }
52};
53
54/* handle :: Either Callback
55 *                  {status:Number*: (result -> Either HTTPResult Any),
56 *                   'default'?: Callback}
57 *           -> HTTPResult
58 */
59HTTPResult.prototype.handle = function(fOrObj) {
60    var f = _.isFunction(fOrObj) ?
61            fOrObj :
62            function(status,result) {
63                if ( status in fOrObj ) {
64                    return fOrObj[status](result);
65                } else if ( 'default' in fOrObj ) {
66                    return fOrObj['default'](status,result);
67                } else {
68                    return result;
69                }
70            };
71    var next = new HTTPResult();
72    var handler = {
73        f: f,
74        next: next
75    };
76    if ( this.isSet() ) {
77        this._fire(handler);
78    } else {
79        this._handlers.push(handler);
80    }
81    return next;
82};
83
84// then :: onSuccess:(result:Any -> status:Number)? ->
85//         onError:(result:Any -> status:Number)? -> HTTPResult
86HTTPResult.prototype.then = function(onSuccess,onError) {
87    var f = function(status,result) {
88        if ( status >= 200 && status < 300 && onSuccess ) {
89            if ( onSuccess ) {
90                result = onSuccess(result,status);
91            }
92        } else {
93            if ( onError ) {
94                result = onError(result,status);
95            }
96        }
97        return result;
98    };
99    return this.handle(f);
100};
101
102HTTPResult.prototype.asCallback = function(status) {
103    status = status || 200;
104    return function(ex,result) {
105        if ( ex ) {
106            this.set(-1,ex);
107        } else {
108            this.set(status,result);
109        }
110    }.bind(this);
111};
112
113// when :: Either HTTPResult Any -> HTTPResult
114when = HTTPResult.when = function(status,valueOrResult) {
115    status = status || 200;
116    if ( valueOrResult instanceof HTTPResult ) {
117        return valueOrResult;
118    } else {
119        return new HTTPResult(status,valueOrResult);
120    }
121};
122
123// ok :: result:Any? -> HTTPResult
124HTTPResult.ok = function(result) {
125    return new HTTPResult(200,result);
126};
127
128// fail :: error:Any? -> HTTPResult
129HTTPResult.fail = function(error) {
130    return new HTTPResult(-1,error);
131};
132
133module.exports = HTTPResult;
Note: See TracBrowser for help on using the repository browser.