Skip to content

Commit f99af1f

Browse files
committed
73 fixed specs
1 parent d4f0ec2 commit f99af1f

File tree

6 files changed

+96
-46
lines changed

6 files changed

+96
-46
lines changed

lib/fsm.iced

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ _ = require('underscore')
33
class FSM
44
constructor: (resource, trace)->
55
@resource = resource
6-
# TODO: Ruby had a good idea, but actually use this if you can do it async
6+
# TODO: actually use this if you can do it async
77
@metadata = {}
88
@trace = trace
99

@@ -52,6 +52,7 @@ class FSM
5252
switch code
5353
when 404
5454
res.res.writeHead(404, {'Content-Type': 'text/plain'})
55+
res.res.statusCode = 404
5556
res.res.write('File Not Found')
5657
when 304
5758
delete res.headers['Content-Type']
@@ -142,9 +143,19 @@ class FSM
142143
# else
143144
# _.find(charsets, (cs)-> cs == charset)
144145

145-
# TODO: implement choose encoding
146+
# TODO: sort using q values
146147
chooseEncoding: (req, res, encoding)->
147-
"identity"
148+
accepted = encoding.split(/,\s*/)
149+
provided = @resource.encodingsProvidedSync(req, res)
150+
match = _.isEmpty(provided)
151+
accepted_encoding = null
152+
accepted_encoding = accepted[0] if match
153+
while !match && accepted.length
154+
accept = accepted.shift().split(/\s*;\s*/)[0].toLowerCase()
155+
match = ((accept == "*") || (provided[accept]?)) #.indexOf(accept) > -1))
156+
accepted_encoding = accept if match
157+
@metadata['accept-encoding'] = accepted_encoding
158+
148159

149160
variances: (req, res)->
150161
accept = if @resource.contentTypesProvidedSync(req, res).length > 1 then ["Accept"] else []
@@ -343,6 +354,8 @@ class FSM
343354
# Acceptable encoding available?
344355
v3f7: (req, res) =>
345356
@tracePush 'v3f7'
357+
# console.log @getHeaderVal(req, "accept-encoding")
358+
# console.log @chooseEncoding(req, res, @getHeaderVal(req, "accept-encoding"))
346359
@decisionTest(@chooseEncoding(req, res, @getHeaderVal(req, "accept-encoding")), req, res, null, 406, @v3g7)
347360

348361
# "@resource exists?"
@@ -417,7 +430,7 @@ class FSM
417430
@resource.movedPermanently req, res, (reply)=>
418431
switch typeof(reply)
419432
when 'string'
420-
response.headers["Location"] = reply
433+
res.headers["Location"] = reply
421434
next(301)
422435
# when 'number'
423436
# next(reply)
@@ -488,7 +501,7 @@ class FSM
488501
next(307)
489502
else
490503
next(reply)
491-
, req, res, true, 301, @v3m5)
504+
, req, res, true, 307, @v3m5)
492505

493506
# "POST?"
494507
v3l7: (req, res) =>
@@ -564,8 +577,9 @@ class FSM
564577
@decisionTest(@resource.allowMissingPost, req, res, true, @v3n11, 410)
565578

566579
stage1Ok: (req, res) =>
567-
@tracePush 'stage1Ok'
568-
if res.isRedirect()
580+
# @tracePush 'stage1Ok'
581+
console.log res.respRedirect()
582+
if res.respRedirect() #isRedirect()
569583
if res.headers['Location']
570584
@respond(req, res, 303)
571585
else
@@ -582,20 +596,22 @@ class FSM
582596
@resource.createPath req, res, (uri)=>
583597
if uri
584598
@resource.baseUri req, res, (baseUri)=>
585-
baseUri = @resource.baseUri() || req.baseUri()
586-
req.dispPath = baseUri + '/' + uri
587-
res.headers['Location'] = req.dispPath
588-
result = @acceptHelper()
589-
if typeof(result) == 'number'
590-
@respond(result)
591-
else
592-
@stage1Ok(req, res)
599+
baseUri ||= req.baseUri()
600+
# req.dispPath = baseUri + '/' + uri
601+
# res.headers['Location'] = req.dispPath()
602+
dispPath = baseUri + '/' + uri
603+
res.headers['Location'] = dispPath
604+
@acceptHelper req, res, (result)=>
605+
if typeof(result) == 'number'
606+
@respond(req, res, result)
607+
else
608+
@stage1Ok(req, res)
593609
else
594610
@errorResponse('postIsCreate w/o createPath')
595611
else
596612
@resource.processPost req, res, (processedPost)=>
597613
if typeof(processedPost)
598-
@respond(processedPost)
614+
@respond(req, res, processedPost)
599615
else if processedPost
600616
# TODO: encodeBodyIfSet()
601617
@stage1Ok(req, res)
@@ -612,11 +628,11 @@ class FSM
612628
@tracePush 'v3o14'
613629
@resource.isConflict req, res, (isConflict)=>
614630
if isConflict
615-
@respond(409)
631+
@respond(req, res, 409)
616632
else
617-
result = @acceptHelper()
633+
result = @acceptHelper(req)
618634
if typeof(res) == 'number'
619-
@respond(result)
635+
@respond(req, res, result)
620636
else
621637
@d(req, res, @v3p11)
622638

@@ -656,7 +672,7 @@ class FSM
656672
@d(req, res, @v3o18b)
657673
]
658674
else
659-
console.log 'd'
675+
# console.log 'd'
660676
@d(req, res, @v3o18b)
661677

662678
v3o18b: (req, res) =>
@@ -666,18 +682,18 @@ class FSM
666682
# Response includes an entity?
667683
v3o20: (req, res) =>
668684
@tracePush 'v3o20'
669-
@decisionTest(req.hasResponseBody(), req, res, true, @v3o18, 204)
685+
@decisionTest(res.hasResponseBody(), req, res, true, @v3o18, 204)
670686

671687
# Conflict?
672688
v3p3: (req, res) =>
673689
@tracePush 'v3p3'
674690
@resource.isConflict req, res, (isConflict)=>
675691
if isConflict
676-
@respond(409)
692+
@respond(req, res, 409)
677693
else
678-
result = @acceptHelper()
694+
result = @acceptHelper(req)
679695
if typeof(res) == 'number'
680-
@respond(result)
696+
@respond(req, res, result)
681697
else
682698
@d(req, res, @v3p11)
683699

@@ -686,19 +702,35 @@ class FSM
686702
@tracePush 'v3p11'
687703
@decisionTest(@getHeaderVal(req, 'location'), req, res, null, @v3o20, 201)
688704

689-
acceptHelper: () ->
690-
null
691-
# CT = case getHeaderVal("Content-Type") of
692-
# undefined -> "application/octet-stream";
693-
# Other -> Other
694-
# end,
705+
# TODO: should require a callback
706+
acceptHelper: (req, res, next) ->
707+
# null
708+
ct = @getHeaderVal(req, 'content-type') || "application/octet-stream"
709+
mt = ct.split(';')[0]
710+
contentTypesAccepted = @resource.contentTypesAcceptedSync()
711+
func = null
712+
func = contentTypesAccepted[mt] if contentTypesAccepted?
713+
if func?
714+
# TODO: allow string or function
715+
# @resource[func].apply
716+
func.apply @resource, [req, res, (result) =>
717+
# encodeBodyIfSet()
718+
next(result)
719+
]
720+
721+
# TODO: encodeBodyIfSet()
722+
# true
723+
else
724+
# @respond(req, res, 415)
725+
# 415
726+
next(415)
727+
695728
# {MT, MParams} = webmachineUtil:mediaTypeToDetail(CT),
696729
# wrcall({setMetadata, 'mediaparams', MParams}),
697-
# case [Fun || {Type,Fun} <-
698-
# resourceCall(contentTypesAcceptedSync), MT =:= Type] of
730+
# case [Fun || {Type, Fun} <- @resource.contentTypesAcceptedSync(), MT =:= Type] of
699731
# [] -> {respond,415};
700732
# AcceptedContentList ->
701-
# F = hd(AcceptedContentList),
733+
# F = AcceptedContentList[0],
702734
# case resourceCall(F) of
703735
# true ->
704736
# encodeBodyIfSet(),

lib/requestData.iced

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ class ReqData
99

1010
## request functions
1111

12+
baseUri: ()->
13+
"#{@url.protocol}//#{@url.host}"
14+
1215
# -> {integer(),integer()} The HTTP version used by the client. Most often 1.1 .
1316
version: ()->
1417
'1.1'

lib/resource.iced

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Resource
1414
charsetsProvidedSync: (req, res) -> {"utf-8" : (x) -> x}
1515
encodingsProvidedSync: (req, res) -> {"identity" : (x) -> x}
1616
contentTypesProvidedSync: (req, res) -> {"text/html" : 'toHtml'}
17-
contentTypesAcceptedSync: (req, res) -> []
17+
contentTypesAcceptedSync: (req, res) -> {}
1818
variancesSync: (req, res) -> []
1919
optionsSync: (req, res) -> []
2020

lib/responseData.iced

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
class ResData
33
constructor: (nodeRes)->
44
@res = nodeRes
5+
@redirect = false
56
@headers = {}
67

7-
isRedirect: ()->
8+
# isRedirect: ()->
89

910
appendToResponseBody: (body)->
1011

@@ -17,7 +18,7 @@ class ResData
1718

1819
# -> bool() the last value passed to doRedirect, false otherwise – if true,
1920
# then some responses will be 303 instead of 2xx where applicable
20-
respRedirect: ()->
21+
respRedirect: ()-> @redirect
2122

2223
# -> mochiheaders() The outgoing HTTP headers. Generally, getRespHeader is
2324
# more useful.
@@ -33,12 +34,13 @@ class ResData
3334

3435
# rd() Given a header name and value, set an outgoing request header to that value.
3536
setRespHeader: (string, value) ->
37+
@headers[string] = value
3638

3739
# rd() Append the given value to the body of the outgoing response.
3840
appendToResponseBody: (binary) ->
3941

4042
# rd() see respRedirect; this sets that value.
41-
doRedirect: (bool) ->
43+
doRedirect: (bool) -> @redirect = bool
4244

4345
# rd() The dispPath is the only path that can be changed during a request. This function will do so.
4446
setDispPath: (string) ->

test/fsm-test.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ var _ = require('underscore'),
1515
var port = 9000;
1616
var baseUrl = '127.0.0.1';
1717

18-
// var test = _.find(scenarios, function(val){
19-
// return val.name == 'v3d5 true';
20-
// });
18+
var test = _.find(scenarios, function(val){
19+
return val.name == process.env.TEST;
20+
});
2121

2222
function buildTest(test) {
2323
return {
@@ -35,6 +35,19 @@ function buildTest(test) {
3535
var mockNodeRes = {
3636
end: function(){
3737
// console.log('done');
38+
},
39+
writeHead: function(code, header){
40+
this.statusCode = code;
41+
this.header = header;
42+
},
43+
setHeader: function(field, header){
44+
if(!this.header) {
45+
this.header = {};
46+
}
47+
this.header[field] = header;
48+
},
49+
write: function(data) {
50+
this.body = data;
3851
}
3952
};
4053
var mockResource = {

test/scenarios.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ module.exports = [
150150
},
151151
{
152152
name: "v3b6 false",
153-
appConfig: { allowedMethodsSync: ["PUT"], knownContentType: false }, //contentTypesAcceptedSync: ["text/plain"] },
153+
appConfig: { allowedMethodsSync: ["PUT"], knownContentType: false }, //contentTypesAcceptedSync: {"text/plain": "textPlain"} },
154154
method: "PUT",
155155
path: "/",
156156
headers: { "Content-type": "application/javascript" },
@@ -159,7 +159,7 @@ module.exports = [
159159
},
160160
{
161161
name: "v3b5 false",
162-
appConfig: { allowedMethodsSync: ["PUT"], knownContentType: false }, //contentTypesAcceptedSync: ["text/plain"] },
162+
appConfig: { allowedMethodsSync: ["PUT"], knownContentType: false }, //contentTypesAcceptedSync: {"text/plain": "textPlain"} },
163163
method: "PUT",
164164
path: "/",
165165
headers: { "Content-type": "application/javascript" },
@@ -393,7 +393,7 @@ module.exports = [
393393
},
394394
{
395395
name: "v3i4 true",
396-
appConfig: { resourceExists: false, allowedMethodsSync: ['PUT'], movedPermanently: function (context) { return("/foo"); } },
396+
appConfig: { resourceExists: false, allowedMethodsSync: ['PUT'], movedPermanently: "/foo" },
397397
method: "PUT",
398398
path: "/",
399399
headers: { },
@@ -420,7 +420,7 @@ module.exports = [
420420
},
421421
{
422422
name: "v3i7 true",
423-
appConfig: { resourceExists: false, allowedMethodsSync: ['PUT'], movedPermanently: function (context) { return("/foo"); } },
423+
appConfig: { resourceExists: false, allowedMethodsSync: ['PUT'], movedPermanently: "/foo" },
424424
method: "PUT",
425425
path: "/",
426426
headers: { },
@@ -528,7 +528,7 @@ module.exports = [
528528
},
529529
{
530530
name: "v3m7 true",
531-
appConfig: { resourceExists: false, allowedMethodsSync: ["POST"], previouslyExisted: false, allowMissingPost: true, postIsCreate: true, createPath: "/", acceptContent: function (context) { context.res.setHeader("Location", "/foo"); return(true) } },
531+
appConfig: { resourceExists: false, allowedMethodsSync: ["POST"], previouslyExisted: false, allowMissingPost: true, postIsCreate: true, createPath: "/", contentTypesAcceptedSync: {"application/octet-stream" : function(req, res, next){ res.doRedirect(true); res.setRespHeader("Location", "/foo"); next(true); } } }, //acceptContent: function (context) { context.res.setHeader("Location", "/foo"); return(true) } },
532532
method: "POST",
533533
path: "/",
534534
headers: { },
@@ -537,7 +537,7 @@ module.exports = [
537537
},
538538
{
539539
name: "v3n5 true",
540-
appConfig: { resourceExists: false, allowedMethodsSync: ["POST"], previouslyExisted: true, movedPermanently: false, movedTemporarily: false, allowMissingPost: true, postIsCreate: true, createPath: "/", acceptContent: function (context) { context.res.setHeader("Location", "/foo"); return(true) } },
540+
appConfig: { resourceExists: false, allowedMethodsSync: ["POST"], previouslyExisted: true, movedPermanently: false, movedTemporarily: false, allowMissingPost: true, postIsCreate: true, createPath: "/", contentTypesAcceptedSync: {"application/octet-stream" : function(req, res, next){ res.doRedirect(true); res.setRespHeader("Location", "/foo"); next(true); } } }, // acceptContent: function (context) { context.res.setHeader("Location", "/foo"); return(true) } },
541541
method: "POST",
542542
path: "/",
543543
headers: { },

0 commit comments

Comments
 (0)