Skip to content

Commit 095f199

Browse files
committed
Fix encoding and charset, update version
1 parent 89a3122 commit 095f199

File tree

7 files changed

+188
-17
lines changed

7 files changed

+188
-17
lines changed

lib/fsm.js

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ FSM.prototype.respond = function(req, res, code, headers) {
139139
break;
140140
case 304:
141141
delete res.headers['Content-Type'];
142+
default:
143+
if(res.respBody()) {
144+
res.res.write(res.respBody());
145+
}
142146
}
143147
res.res.statusCode = code;
144148
if (this.resource.finishRequest != null) {
@@ -185,8 +189,14 @@ FSM.prototype.doChooseCharset = function(charsets, charset, defaultEnc) {
185189
return s.toLowerCase();
186190
});
187191
acceptedCharsets = charset.split(/\s*,\s*/);
188-
accepted = acceptedCharsets.map(function(mt) {
189-
return [1.0, mt];
192+
accepted = acceptedCharsets.map(function(cs) {
193+
cs = cs.split(';');
194+
var ct = cs[0];
195+
var q = cs[1];
196+
if(q) q = q.split('=')[1]
197+
if(q) q = parseFloat(q);
198+
q = q || 1.0;
199+
return [q, ct.toLowerCase()];
190200
});
191201
if (_.contains(acceptedCharsets, defaultEnc)) {
192202
default_priority = 1.0;
@@ -205,24 +215,29 @@ FSM.prototype.doChooseCharset = function(charsets, charset, defaultEnc) {
205215
priority = value[0];
206216
acceptable = value[1];
207217
if (priority === 0.0) {
208-
choices = _.without(choices, acceptable.toLowerCase());
218+
choices = _.without(choices, acceptable);
209219
return false;
210220
} else {
211-
return _.contains(choices, acceptable.toLowerCase());
221+
return _.contains(choices, acceptable);
212222
}
213223
});
214-
if (chosen && _.last(chosen)) {
215-
return _.last(chosen);
216-
} else if (any_ok && _.first(choices)) {
217-
return _.first(choices);
224+
if (chosen && chosen[1]) {
225+
return chosen[1];
226+
} else if (any_ok && choices[0]) {
227+
return choices[0];
218228
} else if (default_ok && _.contains(choices, defaultEnc) && defaultEnc) {
219229
return defaultEnc;
220230
}
221231
};
222232

223233
FSM.prototype.chooseEncoding = function(req, res, encoding) {
224-
var accepted = encoding.split(/,\s*/);
225234
var provided = this.resource.encodingsProvidedSync(req, res);
235+
accepted_encoding = this.doChooseEncoding(provided, encoding);
236+
return this.metadata['accept-encoding'] = accepted_encoding;
237+
};
238+
239+
FSM.prototype.doChooseEncoding = function(provided, encoding) {
240+
var accepted = encoding.split(/,\s*/);
226241
var match = _.isEmpty(provided);
227242
var accepted_encoding = null;
228243
if (match) accepted_encoding = accepted[0];
@@ -232,7 +247,11 @@ FSM.prototype.chooseEncoding = function(req, res, encoding) {
232247
match = (accept === "*") || (provided[accept] != null);
233248
if (match) accepted_encoding = accept;
234249
}
235-
return this.metadata['accept-encoding'] = accepted_encoding;
250+
// TODO: this is likely wrong
251+
if(!accepted_encoding || accepted_encoding === '*') {
252+
accepted_encoding = "identity";
253+
}
254+
return accepted_encoding;
236255
};
237256

238257
FSM.prototype.variances = function(req, res) {
@@ -785,10 +804,15 @@ FSM.prototype.v3o18 = function(req, res) {
785804
contentTypes = self.resource.contentTypesProvidedSync(req, res);
786805
contentType = self.metadata['Content-Type'];
787806
matchingCt = contentTypes[contentType];
788-
self.resource[matchingCt].apply(self.resource, [
807+
matchingRes = self.resource[matchingCt]
808+
if(!matchingRes) {
809+
throw("Expected function "+matchingCt+" for given content-type: "+contentType);
810+
}
811+
matchingRes.apply(self.resource, [
789812
req, res, function(result) {
790813
if (typeof result === 'number') {
791814
self.respond(req, res, result);
815+
// TODO: seems useful to do } else if (typeof result === 'boolean') {
792816
} else {
793817
res.body = result;
794818
self.encodeBody(req, res);

lib/resource.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ Resource.prototype.movedTemporarily = function(req, res, next) {
146146
return next(false);
147147
};
148148

149-
Resource.prototype.finishRequest = function(req, res, next) {
150-
return next(true);
149+
Resource.prototype.finishRequest = function(req, res) {
150+
return true;
151151
};
152152

153153
Resource.prototype.lastModified = function(req, res, next) {

lib/webmachine.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@ Webmachine = (function() {
1515
this.resources = [];
1616
}
1717

18+
Webmachine.prototype.trace = function(tracing) {
19+
this.tracing = tracing;
20+
};
21+
1822
Webmachine.prototype.add = function(resource) {
1923
resource.routeRe = util.pathRegexp(resource.route, (resource.routeReKeys = []), false, false);
2024
return this.resources.push(resource);
2125
};
2226

2327
Webmachine.prototype.start = function(port, ipaddr) {
2428
var _this = this;
29+
var tracing = this.tracing;
2530
this.server = http.createServer(function(req, res) {
2631
var fsm, match, pathInfo, rd, resource, rs, urlForm;
2732
urlForm = url.parse(req.url, true);
@@ -30,8 +35,15 @@ Webmachine = (function() {
3035
rd = new ReqData(req, urlForm, pathInfo);
3136
rs = new ResData(res);
3237
resource = new Resource(resource);
33-
fsm = new Fsm(resource);
34-
return fsm.run(rd, rs);
38+
if(tracing) {
39+
rs.trace = [];
40+
fsm = new Fsm(resource, rs.trace);
41+
} else {
42+
fsm = new Fsm(resource);
43+
}
44+
fsm.run(rd, rs);
45+
if(tracing) { console.dir(rs.trace); }
46+
return true;
3547
} else {
3648
res.writeHead(404, {
3749
'Content-Type': 'text/plain'

npm-debug.log

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
0 info it worked if it ends with ok
2+
1 verbose cli [ 'node', '/usr/local/bin/npm', 'test', 'test/charset-test.js' ]
3+
2 info using npm@1.1.39
4+
3 info using node@v0.8.1
5+
4 verbose node symlink /usr/local/bin/node
6+
5 verbose config file /Users/ericredmond/.npmrc
7+
6 verbose config file /usr/local/etc/npmrc
8+
7 verbose config file /usr/local/lib/node_modules/npm/npmrc
9+
8 verbose read json /Users/ericredmond/Code/webmachine-nodejs/node_modules/test/charset-test.js/package.json
10+
9 error Error: ENOENT, open '/Users/ericredmond/Code/webmachine-nodejs/node_modules/test/charset-test.js/package.json'
11+
9 error { [Error: ENOENT, open '/Users/ericredmond/Code/webmachine-nodejs/node_modules/test/charset-test.js/package.json']
12+
9 error errno: 34,
13+
9 error code: 'ENOENT',
14+
9 error path: '/Users/ericredmond/Code/webmachine-nodejs/node_modules/test/charset-test.js/package.json' }
15+
10 error You may report this log at:
16+
10 error <http://github.com/isaacs/npm/issues>
17+
10 error or email it to:
18+
10 error <npm-@googlegroups.com>
19+
11 error System Darwin 12.3.0
20+
12 error command "node" "/usr/local/bin/npm" "test" "test/charset-test.js"
21+
13 error cwd /Users/ericredmond/Code/webmachine-nodejs
22+
14 error node -v v0.8.1
23+
15 error npm -v 1.1.39
24+
16 error path /Users/ericredmond/Code/webmachine-nodejs/node_modules/test/charset-test.js/package.json
25+
17 error code ENOENT
26+
18 error message ENOENT, open '/Users/ericredmond/Code/webmachine-nodejs/node_modules/test/charset-test.js/package.json'
27+
19 error errno 34
28+
20 error 34 errno
29+
21 verbose exit [ 34, true ]

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"author": "Eric Redmond <eric.redmond@gmail.com>",
33
"name": "webmachine",
44
"description": "Webmachine Application Server",
5-
"version": "0.0.2",
5+
"version": "0.0.3",
66
"preferGlobal": "true",
77
"repository": {
88
"type": "git",
@@ -12,7 +12,7 @@
1212
"license" : "MIT/X11",
1313
"main": "./lib/webmachine.js",
1414
"engines": {
15-
"node": "~>0.6.0"
15+
"node": "=>0.8.0"
1616
},
1717
"dependencies": {
1818
"optimist" : "~>0.2.0",

test/charset-test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
var _ = require('underscore'),
2+
vows = require('vows'),
3+
assert = require('assert'),
4+
Resource = require('../lib/resource'),
5+
Fsm = require('../lib/fsm');
6+
7+
8+
9+
vows.describe('FSM Charset').addBatch({
10+
'given a charset': {
11+
topic: function () {
12+
root = {
13+
route: '/'
14+
};
15+
var resource = new Resource(root);
16+
var fsm = new Fsm(resource);
17+
var potentials = ["utf-8"];
18+
var acceptcharset = 'ISO-8859-1,utf-8;q=0.7,*;q=0.3';
19+
var defaultEnc = "utf-8";
20+
var charset = fsm.doChooseCharset(potentials, acceptcharset, defaultEnc);
21+
this.callback(true, charset);
22+
},
23+
'default to utf8': function (passed, charset) {
24+
assert.equal(charset, 'utf-8');
25+
}
26+
}
27+
// define a ISO-8859-1 function, choose that
28+
// check that * works against a lower q match
29+
}).export(module);

test/encoding-test.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
var _ = require('underscore'),
2+
vows = require('vows'),
3+
assert = require('assert'),
4+
Resource = require('../lib/resource'),
5+
Fsm = require('../lib/fsm');
6+
7+
vows.describe('FSM Encoding').addBatch({
8+
'given all encodings': {
9+
topic: function () {
10+
root = {
11+
route: '/'
12+
};
13+
var resource = new Resource(root);
14+
var fsm = new Fsm(resource);
15+
var identityFunc = function(x){ return x; };
16+
var provided = {"deflate":identityFunc,"identity":identityFunc};
17+
var acceptencoding = '*';
18+
var encoding = fsm.doChooseEncoding(provided, acceptencoding);
19+
this.callback(true, encoding);
20+
},
21+
'default to identity': function (passed, charset) {
22+
assert.equal(charset, 'identity');
23+
}
24+
},
25+
'given identity encoding': {
26+
topic: function () {
27+
root = {
28+
route: '/'
29+
};
30+
var resource = new Resource(root);
31+
var fsm = new Fsm(resource);
32+
var identityFunc = function(x){ return x; };
33+
var provided = {"deflate":identityFunc,"identity":identityFunc};
34+
var acceptencoding = 'identity';
35+
var encoding = fsm.doChooseEncoding(provided, acceptencoding);
36+
this.callback(true, encoding);
37+
},
38+
'choose identity': function (passed, charset) {
39+
assert.equal(charset, 'identity');
40+
}
41+
},
42+
'given deflate encoding': {
43+
topic: function () {
44+
root = {
45+
route: '/'
46+
};
47+
var resource = new Resource(root);
48+
var fsm = new Fsm(resource);
49+
var identityFunc = function(x){ return x; };
50+
var provided = {"deflate":identityFunc,"identity":identityFunc};
51+
var acceptencoding = 'deflate';
52+
var encoding = fsm.doChooseEncoding(provided, acceptencoding);
53+
this.callback(true, encoding);
54+
},
55+
'choose deflate': function (passed, charset) {
56+
assert.equal(charset, 'deflate');
57+
}
58+
},
59+
'given no valid encoding': {
60+
topic: function () {
61+
root = {
62+
route: '/'
63+
};
64+
var resource = new Resource(root);
65+
var fsm = new Fsm(resource);
66+
var identityFunc = function(x){ return x; };
67+
var provided = {"identity":identityFunc};
68+
var acceptencoding = 'derp';
69+
var encoding = fsm.doChooseEncoding(provided, acceptencoding);
70+
this.callback(true, encoding);
71+
},
72+
'choose identity': function (passed, charset) {
73+
assert.equal(charset, 'identity');
74+
}
75+
}
76+
// check that * works against a lower q match
77+
}).export(module);

0 commit comments

Comments
 (0)