11/*jslint node: true*/
2- " use strict" ;
2+ ' use strict' ;
33
44var mime = require ( 'mime' ) ;
55var fs = require ( 'fs' ) ;
@@ -8,91 +8,114 @@ var path = require('path');
88var $rdf = require ( 'rdflib' ) ;
99var S = require ( 'string' ) ;
1010var async = require ( 'async' ) ;
11+ var Negotiator = require ( 'negotiator' )
1112
1213var debug = require ( '../debug' ) . handlers ;
1314var acl = require ( '../acl.js' ) ;
1415var header = require ( '../header.js' ) ;
1516var metadata = require ( '../metadata.js' ) ;
1617var ns = require ( '../vocab/ns.js' ) . ns ;
1718var utils = require ( '../utils.js' ) ;
19+ var translate = require ( '../utils.js' ) . translate ;
1820var HttpError = require ( '../http-error' ) ;
21+ var parse = require ( '../utils.js' ) . parse ;
1922
2023var ldpVocab = require ( '../vocab/ldp.js' ) ;
2124
22- function get ( req , res , next ) {
25+ var RDFs = [
26+ 'text/turtle' ,
27+ 'application/n3' ,
28+ 'application/nquads' ,
29+ 'application/n-quads' ,
30+ 'text/n3' ,
31+ 'application/rdf+xml' ,
32+ 'application/ld+json' ,
33+ 'application/x-turtle'
34+ ]
35+
36+ function get ( req , res , next ) {
2337 var ldp = req . app . locals . ldp ;
24- var uri = utils . uriBase ( req ) ;
25- var filename = utils . uriToFilename ( req . path , ldp . root ) ;
26-
2738 var includeBody = req . method === 'GET'
2839
29- // Parse accept mime types into a priority (q) ordered array
30- res . acceptTypes = header . negotiateContentType ( req ) || 'text/turtle' ;
40+ var negotiator = new Negotiator ( req )
41+ var requestedType = negotiator . mediaType ( )
42+ var possibleRDFType = negotiator . mediaType ( RDFs )
3143
32- // Set headers
44+ var baseUri = utils . uriBase ( req ) ;
3345 res . header ( 'MS-Author-Via' , 'SPARQL' ) ;
3446
3547 // Set live updates
3648 if ( ldp . live ) {
3749 res . header ( 'Updates-Via' , utils . uriBase ( req ) ) ;
3850 }
3951
40- debug ( req . method + ' -- ' + req . originalUrl ) ;
52+ console . log ( 'METHOD' , req . method )
53+ debug ( req . method + ' requesting -- ' + req . originalUrl ) ;
4154
4255 // Get resource or container
43- ldp . get ( filename , uri , includeBody , function ( err , data , container ) {
56+ ldp . get ( req . path , baseUri , includeBody , possibleRDFType ,
57+ function ( err , stream , contentType , container ) {
4458
45- // This should be implemented in LDP.prototype.get
46- if ( err && err . status === 404 && glob . hasMagic ( filename ) ) {
47- debug ( "GET/HEAD -- Glob request" ) ;
59+ console . log ( 'file appears to be' , contentType )
60+ // use globHandler if magic is detected
61+ if ( err && err . status === 404 && glob . hasMagic ( req . path ) ) {
62+ debug ( req . method + ' -- Glob request' ) ;
4863 return globHandler ( req , res , next ) ;
4964 }
5065
51-
66+ // Handle error
5267 if ( err ) {
53- debug ( 'GET/HEAD -- Read error : ' + err . status + ' ' + err . message ) ;
68+ debug ( req . method + ' -- Error : ' + err . status + ' ' + err . message ) ;
5469 return next ( err ) ;
5570 }
5671
57- // Just return that file exists
58- // data is of `typeof 'string'` if file is empty, but exists!
59- if ( data === undefined ) {
60- res . sendStatus ( 200 ) ;
61- return next ( ) ;
72+ // Till here it must exist
73+ if ( ! includeBody ) {
74+ debug ( 'HEAD only -- ' + req . originalUrl ) ;
75+ return res . send ( 200 )
6276 }
6377
64- // Container/resource retrieved
65- if ( ! container ) {
66- var contentType = mime . lookup ( filename ) ;
67- res . set ( 'content-type' , contentType ) ;
68- debug ( 'GET/HEAD -- content-type: ' + contentType ) ;
69-
70- if ( utils . hasSuffix ( filename , ldp . turtleExtensions ) ) {
71- contentType = 'text/turtle' ;
72- }
78+ // Handle skin
79+ if ( container &&
80+ requestedType . indexOf ( 'text/html' ) === 0 &&
81+ ldp . skin ) {
82+ var address = req . protocol + '/' + req . get ( 'host' ) + req . originalUrl ;
83+ return res . redirect ( 303 , ldp . skin + address ) ;
84+ }
7385
74- // if data is not text/turtle, just send it
75- if ( contentType !== 'text/turtle' ) {
76- return res
77- . status ( 200 )
78- . sendFile ( path . resolve ( filename ) ) ;
79- }
86+ // If request accepts the content-type we found
87+ if ( negotiator . mediaType ( [ contentType ] ) ) {
88+ debug ( 'GET -- ' + req . originalUrl + ' no translation ' + contentType ) ;
89+ res . setHeader ( 'content-type' , contentType )
90+ return stream . pipe ( res )
8091 }
8192
82- // redirect to file browser if we got text/html with highest priority
83- if ( container &&
84- res . acceptTypes . indexOf ( 'text/html' ) === 0 &&
85- ldp . skin ) {
86- return res . redirect ( 303 , ldp . skin + req . protocol + '/' + req . get ( 'host' ) + req . originalUrl ) ;
93+ // If it is not in our RDFs we can't even translate,
94+ // Sorry, we can't help
95+ if ( ! possibleRDFType ) {
96+ var err = new Error ( 'Cannot server your type' )
97+ err . status = 406
98+ return next ( err ) ;
8799 }
88100
89- // TODO this should be added as a middleware in the routes
90- res . locals . turtleData = data ;
91- return parseLinkedData ( req , res , next ) ;
101+
102+ // Translate from the contentType found to the possibleRDFType desired
103+ translate ( stream , baseUri , contentType , possibleRDFType , function ( err , data ) {
104+ if ( err ) {
105+ debug ( 'GET ERROR translating: ' + req . originalUrl + ' ' + contentType + ' -> ' + possibleRDFType + ' -- ' + 500 + err . message ) ;
106+ return next ( new HttpError ( {
107+ message : err . message ,
108+ status : 500
109+ } ) )
110+ }
111+ debug ( 'GET -- ' + req . originalUrl + ' translating ' + contentType + ' -> ' + possibleRDFType ) ;
112+ res . setHeader ( 'Content-Type' , possibleRDFType )
113+ return res . send ( data ) ;
114+ } ) ;
92115 } ) ;
93116}
94117
95- function globHandler ( req , res , next ) {
118+ function globHandler ( req , res , next ) {
96119 var ldp = req . app . locals . ldp ;
97120 var filename = utils . uriToFilename ( req . path , ldp . root ) ;
98121 var uri = utils . uriBase ( req ) ;
@@ -102,27 +125,27 @@ function globHandler(req, res, next) {
102125 nobrace : true
103126 } ;
104127
105- glob ( filename , globOptions , function ( err , matches ) {
128+ glob ( filename , globOptions , function ( err , matches ) {
106129 if ( err || matches . length === 0 ) {
107- debug ( " GET/HEAD -- No files matching the pattern" ) ;
130+ debug ( ' GET/HEAD -- No files matching the pattern' ) ;
108131 return next ( new HttpError ( {
109- message : " No files matching glob pattern" ,
132+ message : ' No files matching glob pattern' ,
110133 status : 404
111134 } ) ) ;
112135 }
113136
114137 // Matches found
115138 var globGraph = $rdf . graph ( ) ;
116139
117- async . each ( matches , function ( match , done ) {
140+ async . each ( matches , function ( match , done ) {
118141 var baseUri = utils . filenameToBaseUri ( match , uri , ldp . root ) ;
119- fs . readFile ( match , { encoding : " utf8" } , function ( err , fileData ) {
142+ fs . readFile ( match , { encoding : ' utf8' } , function ( err , fileData ) {
120143 if ( err ) {
121144 debug ( 'GET -- Error in globHandler' + err ) ;
122145 return done ( null ) ;
123146 }
124147 aclAllow ( match , req , res , function ( allowed ) {
125- if ( ! S ( match ) . endsWith ( " .ttl" ) || ! allowed ) {
148+ if ( ! S ( match ) . endsWith ( ' .ttl' ) || ! allowed ) {
126149 return done ( null ) ;
127150 }
128151 try {
@@ -144,13 +167,13 @@ function globHandler(req, res, next) {
144167 null ,
145168 'text/turtle' ) ;
146169 // TODO this should be added as a middleware in the routes
147- res . locals . turtleData = data ;
148- return parseLinkedData ( req , res , next ) ;
170+ res . setHeader ( 'Content-Type' , 'text/turtle' )
171+ res . send ( data )
149172 } ) ;
150173 } ) ;
151174}
152175
153- function aclAllow ( match , req , res , callback ) {
176+ function aclAllow ( match , req , res , callback ) {
154177 var ldp = req . app . locals . ldp ;
155178
156179 if ( ! ldp . webid ) {
@@ -159,60 +182,9 @@ function aclAllow(match, req, res, callback) {
159182
160183 var relativePath = '/' + path . relative ( ldp . root , match ) ;
161184 res . locals . path = relativePath ;
162- acl . allow ( " Read" , req , res , function ( err ) {
185+ acl . allow ( ' Read' , req , res , function ( err ) {
163186 callback ( err ) ;
164187 } ) ;
165188}
166189
167- function parseLinkedData ( req , res , next ) {
168- var ldp = req . app . locals . ldp ;
169- var filename = utils . uriToFilename ( req . path , ldp . root ) ;
170- var uri = utils . uriBase ( req ) ;
171- var turtleData = res . locals . turtleData ;
172-
173- var accept = header . parseAcceptRDFHeader ( req ) || 'text/turtle' ;
174- var baseUri = utils . filenameToBaseUri ( filename , uri , ldp . root ) ;
175-
176- // Handle Turtle Accept header
177- if ( accept === 'text/turtle' ||
178- accept === 'text/n3' ||
179- accept === 'application/turtle' ||
180- accept === 'application/n3' ) {
181- res . status ( 200 )
182- . set ( 'content-type' , accept )
183- . send ( turtleData ) ;
184- return next ( ) ;
185- }
186-
187- //Handle other file types
188- var resourceGraph = $rdf . graph ( ) ;
189- try {
190- $rdf . parse ( turtleData , resourceGraph , baseUri , 'text/turtle' ) ;
191- } catch ( err ) {
192-
193- debug ( "GET/HEAD -- Error parsing data: " + err . message ) ;
194- return next ( new HttpError ( {
195- message : err . message ,
196- status : 500
197- } ) ) ;
198- }
199-
200- // Graph to `accept` type
201- $rdf . serialize ( undefined , resourceGraph , null , accept , function ( err , result ) {
202- if ( result === undefined || err ) {
203- debug ( "GET/HEAD -- Serialization error: " + err ) ;
204- return next ( new HttpError ( {
205- message : err . message ,
206- status : 500
207- } ) ) ;
208- }
209- res
210- . status ( 200 )
211- . set ( 'content-type' , accept )
212- . send ( result ) ;
213-
214- return next ( ) ;
215- } ) ;
216- }
217-
218190exports . handler = get ;
0 commit comments