-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
161 lines (143 loc) · 4.1 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
'use strict';
//
// Plugin name.
//
exports.name = 'xhr';
/**
* The server-side plugin for BigPipe which adds a proxy function.
*
* @param {BigPipe} pipe The BigPipe instance.
* @param {Object} options Optional options.
* @api public
*/
exports.server = function server(pipe, options) {
pipe.on('transform:pagelet:after', function optimized(Pagelet, next) {
/**
* Helper that will send a JSON response with a render `false` flag.
* This ensures the client does not re-render the target pagelet.
* Only define this helper if the Pagelet does not have a defined
* readable, this could potentially destory a Pagelet that does not require
* this plugin to work.
*
* @param {Object} data JSON data that needs to be written to the response
* @return {Pagelet} fluent interface
*/
if (!Pagelet.prototype.plain) Pagelet.readable('plain', function plain(data) {
this._res.setHeader('plain', true);
this.end(data);
return this;
});
next(null, Pagelet);
});
};
/**
* The client-side plugin for BigPipe which adds XHR functionality.
*
* @param {BigPipe} pipe The BigPipe instance.
* @param {Object} options Optional options.
* @api public
*/
exports.client = function client(pipe, options) {
pipe.on('create', function created(pagelet) {
var xhr = require('xhr')
, async = pagelet.xhr = {};
/**
* Proxy XHR GET request.
*
* @param {String} uri Target url.
* @param {Function} done Completion callback.
* @api public
*/
async.get = function get(uri, done) {
xhr({ method: 'get', uri: uri }, process(done));
};
/**
* Proxy XHR POST request.
*
* @param {String} uri Target url.
* @param {Object} data Optional data.
* @param {Function} done Completion callback.
* @api public
*/
async.post = function post(uri, data, done) {
if ('function' !== typeof done) {
done = data;
data = {};
}
var object = {
method: 'post',
uri: uri
};
object['string' === typeof data ? 'body' : 'json'] = data;
xhr(object, process(done));
};
/**
* Proxy XHR PUT request.
*
* @param {String} uri Target url.
* @param {Object} data Optional data.
* @param {Function} done Completion callback.
* @api public
*/
async.put = function put(uri, data, done) {
if ('function' !== typeof done) {
done = data;
data = {};
}
var object = {
method: 'put',
uri: uri
};
object['string' === typeof data ? 'body' : 'json'] = data;
xhr(object, process(done));
};
/**
* Proxy XHR DELETE request.
*
* @param {String} uri Target url.
* @param {Function} done Completion callback.
* @api public
*/
async.delete = function get(uri, done) {
xhr({ method: 'delete', uri: uri }, process(done));
};
/**
* Return function that processes the response to XHR.
*
* @param {Function} done Completion callback.
* @return {Function} processor
* @api private.
*/
function process(done) {
/**
* Process the XHR response. If the header `plain` is set to `true`,
* return the data directly to the callback.
*
* @param {Error} error
* @param {XMLHttpRequest} response
* @param {Mixed} body HTML or JSON
* @api private
*/
return function complete(error, response, body) {
var headers = response.headers || {}
, status = response.statusCode || 500;
if (error || status >= 400) {
return done(error || new Error('Status: '+ status));
}
//
// Plain response header set, do not re-render the pagelet.
//
if (headers.plain === 'true') {
return done(null, response, body);
}
//
// Process the returned data and render the Pagelet.
//
pipe.once(pagelet.name +':render', function rendered(html) {
done(null, response, body);
});
pagelet.render(body);
};
}
});
};