9
9
import arrow
10
10
11
11
from flask import (
12
- Blueprint , g , make_response , render_template ,
12
+ Blueprint , Response , g , make_response , render_template ,
13
13
request , send_file )
14
- from rdflib import Graph
14
+ from rdflib import Graph , plugin , parser #, serializer
15
15
16
16
from lakesuperior .api import resource as rsrc_api
17
17
from lakesuperior .dictionaries .namespaces import ns_collection as nsc
28
28
from lakesuperior .toolbox import Toolbox
29
29
30
30
31
- logger = logging .getLogger (__name__ )
32
-
33
- # Blueprint for LDP REST API. This is what is usually found under `/rest/` in
34
- # standard fcrepo4. Here, it is under `/ldp` but initially `/rest` can be kept
35
- # for backward compatibility.
31
+ DEFAULT_RDF_MIMETYPE = 'text/turtle'
32
+ """
33
+ Fallback serialization format used when no acceptable formats are specified.
34
+ """
36
35
37
- ldp = Blueprint (
38
- 'ldp' , __name__ , template_folder = 'templates' ,
39
- static_url_path = '/static' , static_folder = 'templates/static' )
36
+ logger = logging .getLogger (__name__ )
37
+ rdf_parsable_mimetypes = {
38
+ mt .name for mt in plugin .plugins ()
39
+ if mt .kind is parser .Parser and '/' in mt .name
40
+ }
41
+ """MIMEtypes that can be parsed into RDF."""
40
42
41
- accept_patch = (
42
- 'application/sparql-update' ,
43
- )
44
- accept_rdf = (
43
+ rdf_serializable_mimetypes = {
44
+ #mt.name for mt in plugin.plugins()
45
+ #if mt.kind is serializer.Serializer and '/' in mt.name
45
46
'application/ld+json' ,
46
47
'application/n-triples' ,
47
48
'application/rdf+xml' ,
48
- #'application/x-turtle',
49
- #'application/xhtml+xml',
50
- #'application/xml',
51
- #'text/html',
52
- 'text/n3' ,
53
- #'text/plain',
54
- 'text/rdf+n3' ,
55
49
'text/turtle' ,
50
+ 'text/n3' ,
51
+ }
52
+ """
53
+ MIMEtypes that RDF can be serialized into.
54
+
55
+ These are not automatically derived from RDFLib because only triple
56
+ (not quad) serializations are applicable.
57
+ """
58
+
59
+ accept_patch = (
60
+ 'application/sparql-update' ,
56
61
)
57
62
58
63
std_headers = {
59
64
'Accept-Patch' : ',' .join (accept_patch ),
60
- 'Accept-Post' : ',' .join (accept_rdf ),
61
- #'Allow' : ','.join(allow),
65
+ 'Accept-Post' : ',' .join (rdf_parsable_mimetypes ),
62
66
}
63
67
64
68
"""Predicates excluded by view."""
65
69
vw_blacklist = {
66
70
}
67
71
68
72
73
+ ldp = Blueprint (
74
+ 'ldp' , __name__ , template_folder = 'templates' ,
75
+ static_url_path = '/static' , static_folder = 'templates/static' )
76
+ """
77
+ Blueprint for LDP REST API. This is what is usually found under ``/rest/`` in
78
+ standard fcrepo4. Here, it is under ``/ldp`` but initially ``/rest`` will be
79
+ kept for backward compatibility.
80
+ """
81
+
82
+ ## ROUTE PRE- & POST-PROCESSING ##
69
83
70
84
@ldp .url_defaults
71
85
def bp_url_defaults (endpoint , values ):
@@ -140,16 +154,20 @@ def get_resource(uid, out_fmt=None):
140
154
return _tombstone_response (e , uid )
141
155
else :
142
156
if out_fmt is None :
157
+ rdf_mimetype = _best_rdf_mimetype ()
143
158
out_fmt = (
144
159
'rdf'
145
- if isinstance (rsrc , LdpRs ) or is_accept_hdr_rdf_parsable ()
160
+ if isinstance (rsrc , LdpRs ) or rdf_mimetype is not None
146
161
else 'non_rdf' )
147
162
out_headers .update (_headers_from_metadata (rsrc ))
148
163
uri = g .tbox .uid_to_uri (uid )
149
164
if out_fmt == 'rdf' :
165
+ if locals ().get ('rdf_mimetype' , None ) is None :
166
+ rdf_mimetype = DEFAULT_RDF_MIMETYPE
150
167
ggr = g .tbox .globalize_graph (rsrc .out_graph )
151
168
ggr .namespace_manager = nsm
152
- return _negotiate_content (ggr , out_headers , uid = uid , uri = uri )
169
+ return _negotiate_content (
170
+ ggr , rdf_mimetype , out_headers , uid = uid , uri = uri )
153
171
else :
154
172
if not getattr (rsrc , 'local_path' , False ):
155
173
return ('{} has no binary content.' .format (rsrc .uid ), 404 )
@@ -174,6 +192,7 @@ def get_version_info(uid):
174
192
175
193
:param str uid: UID of resource to retrieve versions for.
176
194
"""
195
+ rdf_mimetype = _best_rdf_mimetype () or DEFAULT_RDF_MIMETYPE
177
196
try :
178
197
gr = rsrc_api .get_version_info (uid )
179
198
except ResourceNotExistsError as e :
@@ -183,7 +202,7 @@ def get_version_info(uid):
183
202
except TombstoneError as e :
184
203
return _tombstone_response (e , uid )
185
204
else :
186
- return _negotiate_content (g .tbox .globalize_graph (gr ))
205
+ return _negotiate_content (g .tbox .globalize_graph (gr ), rdf_mimetype )
187
206
188
207
189
208
@ldp .route ('/<path:uid>/fcr:versions/<ver_uid>' , methods = ['GET' ])
@@ -194,6 +213,7 @@ def get_version(uid, ver_uid):
194
213
:param str uid: Resource UID.
195
214
:param str ver_uid: Version UID.
196
215
"""
216
+ rdf_mimetype = _best_rdf_mimetype () or DEFAULT_RDF_MIMETYPE
197
217
try :
198
218
gr = rsrc_api .get_version (uid , ver_uid )
199
219
except ResourceNotExistsError as e :
@@ -203,7 +223,7 @@ def get_version(uid, ver_uid):
203
223
except TombstoneError as e :
204
224
return _tombstone_response (e , uid )
205
225
else :
206
- return _negotiate_content (g .tbox .globalize_graph (gr ))
226
+ return _negotiate_content (g .tbox .globalize_graph (gr ), rdf_mimetype )
207
227
208
228
209
229
@ldp .route ('/<path:parent_uid>' , methods = ['POST' ], strict_slashes = False )
@@ -225,7 +245,7 @@ def post_resource(parent_uid):
225
245
handling , disposition = set_post_put_params ()
226
246
stream , mimetype = _bistream_from_req ()
227
247
228
- if LdpFactory . is_rdf_parsable ( mimetype ) :
248
+ if mimetype in rdf_parsable_mimetypes :
229
249
# If the content is RDF, localize in-repo URIs.
230
250
global_rdf = stream .read ()
231
251
rdf_data = g .tbox .localize_payload (global_rdf )
@@ -277,7 +297,7 @@ def put_resource(uid):
277
297
handling , disposition = set_post_put_params ()
278
298
stream , mimetype = _bistream_from_req ()
279
299
280
- if LdpFactory . is_rdf_parsable ( mimetype ) :
300
+ if mimetype in rdf_parsable_mimetypes :
281
301
# If the content is RDF, localize in-repo URIs.
282
302
global_rdf = stream .read ()
283
303
rdf_data = g .tbox .localize_payload (global_rdf )
@@ -459,7 +479,19 @@ def patch_version(uid, ver_uid):
459
479
460
480
## PRIVATE METHODS ##
461
481
462
- def _negotiate_content (gr , headers = None , ** vw_kwargs ):
482
+ def _best_rdf_mimetype ():
483
+ """
484
+ Check if any of the 'Accept' header values provided is a RDF parsable
485
+ format.
486
+ """
487
+ for accept in request .accept_mimetypes :
488
+ mimetype = accept [0 ]
489
+ if mimetype in rdf_parsable_mimetypes :
490
+ return mimetype
491
+ return None
492
+
493
+
494
+ def _negotiate_content (gr , rdf_mimetype , headers = None , ** vw_kwargs ):
463
495
"""
464
496
Return HTML or serialized RDF depending on accept headers.
465
497
"""
@@ -470,7 +502,9 @@ def _negotiate_content(gr, headers=None, **vw_kwargs):
470
502
else :
471
503
for p in vw_blacklist :
472
504
gr .remove ((None , p , None ))
473
- return (gr .serialize (format = 'turtle' ), headers )
505
+ return Response (
506
+ gr .serialize (format = rdf_mimetype ), 200 , headers ,
507
+ mimetype = rdf_mimetype )
474
508
475
509
476
510
def _bistream_from_req ():
@@ -534,17 +568,6 @@ def set_post_put_params():
534
568
return handling , disposition
535
569
536
570
537
- def is_accept_hdr_rdf_parsable ():
538
- """
539
- Check if any of the 'Accept' header values provided is a RDF parsable
540
- format.
541
- """
542
- for mimetype in request .accept_mimetypes .values ():
543
- if LdpFactory .is_rdf_parsable (mimetype ):
544
- return True
545
- return False
546
-
547
-
548
571
def parse_repr_options (retr_opts ):
549
572
"""
550
573
Set options to retrieve IMR.
0 commit comments