Coverage report: /development/source/library/org/datagraph/spocq-shard/src/spocq-server/sesame.lisp
| Kind | Covered | All | % |
| expression | 0 | 830 | 0.0 |
| branch | 0 | 34 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; -*- Mode: lisp; Syntax: ansi-common-lisp; Base: 10; Package: org.datagraph.spocq.server.implementation; -*-
2
;;; Copyright 2013 [james anderson](mailto:james.anderson@setf.de) All Rights Reserved
4
(in-package :org.datagraph.spocq.server.implementation)
6
(:documentation "sparql sesame2 protocol"
8
"This file implements ths responses to the documented 'HTTP communication protocol for Sesame 2'
9
(http://openrdf.callimachus.net/sesame/2.7/docs/system.docbook?view#chapter-http-protocol),
10
whereby operations defined in the graph store protocol are delegated to its response operator.
14
/protocol : protocol version (GET)
15
/repositories : overview of available repositories (GET)
16
/${STORE_REPOSITORY} : query evaluation and administration tasks on
17
a repository (GET/POST/DELETE)
18
/statements : repository statements (GET/POST/PUT/DELETE)
19
/contexts : context overview (GET)
20
/size : #statements in repository (GET)
21
/rdf-graphs : named graphs overview (GET)
22
/service : Graph Store operations on indirectly referenced named graphs
23
in repository (GET/PUT/POST/DELETE)
24
includes the query argument graph=${STORE_IGRAPH}
25
/${STORE_RGRAPH} : Graph Store operations on directly referenced named graphs
26
in repository (GET/PUT/POST/DELETE)
27
/namespaces : overview of namespace definitions (GET/DELETE)
28
/${STORE_PREFIX} : namespace-prefix definition (GET/PUT/DELETE)
30
See resources.lisp for the class definitions
34
(http:def-resource-function sesame-protocol-id (resource request response)
36
(:encode :default mime:text/plain)
37
(:get ((resource |/:account/protocol|) request response (request-type t) (response-type t))
38
(setf (http:response-content-disposition response) '("attachment" "filename" "protocol.txt"))
43
(http:def-resource-function sesame-metadata-as-sparql-results (resource request response)
45
"Respond to requests for repository metadata:
46
contexts, namespaces, size are implemented directly.
47
statements operations relegate to the graph store implementation.")
51
(:auth http:authenticate-request-password)
52
(:auth http:authenticate-request-token)
53
(:auth http:authenticate-request-session)
54
(:auth http:authenticate-request-location)
56
(:auth http:authorize-request)
58
(:encode :default mime:application/sparql-results+json)
59
(:encode mime:application/sparql-results+xml)
60
(:encode mime:application/json)
62
(:decode mime:application/json)
64
(:get ((resource |/:account/repositories|) request response)
65
"Return a list of the account repositories with access information
66
respective the request agent. This includes only those repositories with
67
read or write access, which means, absent an authenticated agent, just the
69
(compute-get-accounts-repositories (resource-account resource) (http:request-agent request)))
71
(:post ((resource |/:account/repositories|) request response)
73
(let* ((specification (call-next-method))
74
(account (resource-account resource))
75
(repository-spec (rest (assoc "repository" specification :test #'equalp)))
76
(repository-name (typecase repository-spec
77
(cons (rest (assoc "name" repository-spec :test #'equalp)))
78
(string repository-spec))))
80
(compute-post-accounts-repositories account request response `(:name ,repository-name))
81
(http:bad-request "A repository name is required."))))
83
(:get ((resource |/:account/repositories/:repository/contexts|) request response request-type mime:application/sparql-results)
84
(compute-get-contexts (resource-repository resource) (http:request-agent request)))
86
(:get ((resource |/:account/repositories/:repository/namespaces|) request response)
87
(let ((bindings (dydra:metadata-namespace-bindings (resource-repository resource))))
88
(dydra:make-list-solution-field :dimensions '(?::prefix ?::namespace)
89
:solutions (loop for (prefix . iri) in bindings
90
collect (list prefix (dydra:iri-lexical-form iri))))))
92
(:delete ((resource |/:account/repositories/:repository/namespaces|) request response)
93
(http:not-implemented))
97
(http:def-resource-function sesame-metadata-as-text (resource request response)
99
"Respond to requests for repository metadata for which the default response media type is text/plain:
100
an individual namespace
105
(:auth http:authenticate-request-password)
106
(:auth http:authenticate-request-token)
107
(:auth http:authenticate-request-session)
108
(:auth http:authenticate-request-location)
110
(:auth http:authorize-request)
112
(:encode :default mime:text/plain)
113
(:encode mime:application/sparql-results+json)
114
(:encode mime:application/sparql-results+xml)
116
(:decode mime:application/json)
118
(:get ((resource |/:account/repositories/:repository/namespaces/:prefix|) request response (request-type t) (response-type mime:application/sparql-results))
119
(let* ((bindings (dydra:metadata-namespace-bindings (resource-repository resource)))
120
(prefix (resource-prefix resource))
121
(namespace-iri (rest (assoc prefix bindings :test #'equal))))
123
(dydra:make-list-solution-field :dimensions '(?::namespace)
124
:solutions `((,(dydra:iri-lexical-form namespace-iri)))))
126
(http:not-found "Undefined prefix: ~a" prefix)))))
127
(:get ((resource |/:account/repositories/:repository/namespaces/:prefix|) request response (request-type t) (response-type mime:text/plain))
128
(let* ((bindings (dydra:metadata-namespace-bindings (resource-repository resource)))
129
(prefix (resource-prefix resource))
130
(namespace-iri (rest (assoc prefix bindings :test #'equal))))
132
(dydra:iri-lexical-form namespace-iri))
134
(http:not-found "Undefined prefix: ~a" prefix)))))
136
(:put ((resource |/:account/repositories/:repository/namespaces/:prefix|) request response)
137
(http:not-implemented))
139
(:delete ((resource |/:account/repositories/:repository/namespaces/:prefix|) request response)
140
(http:not-implemented))
142
(:get ((resource |/:account/repositories/:repository/size|) request response (request-type t) (response-type mime:application/sparql-results))
143
(let ((size (compute-get-size (resource-repository resource) :context-list (http:request-query-arguments request "context"))))
144
(dydra:make-list-solution-field :dimensions '(?::size)
145
:solutions `((,size)))))
146
(:get ((resource |/:account/repositories/:repository/size|) request response (request-type t) (response-type mime:text/plain))
147
(compute-get-size (resource-repository resource) :context-list (http:request-query-arguments request "context")))
151
(http:def-resource-function sesame-statements (resource request response)
153
"Respond to requests for repository content, whereby the response it an rdf document.
154
statements operations relegate to the graph store implementation.")
158
(:auth http:authenticate-request-password)
159
(:auth http:authenticate-request-token)
160
(:auth http:authenticate-request-session)
162
(:auth http:authorize-request)
164
(:encode mime:application/trix)
165
(:encode mime:application/rdf+json)
166
(:encode :default mime:application/n-quads)
167
(:encode mime:application/n-triples)
168
(:encode mime:application/ld+json)
169
(:encode mime:application/rdf+xml)
170
(:encode mime:application/vnd.dydra.sparql-query-algebra)
171
(:encode mime:application/sparql-results+json)
172
(:encode mime:application/sparql-results+xml)
173
(:encode mime:text/csv)
174
(:encode mime:text/tab-separated-values)
175
(:encode mime:text/turtle)
176
(:encode mime:text/vnd.dydra.sparql-query-algebra+graphviz)
177
(:encode mime:text/x-graphviz)
179
#+(or) ; incorrect, get must be a sparql request
180
(:get ((resource |/:account/repositories/:repository|) request response request-type (response-type mime:rdf))
181
(graph-store-get-graph resource request response request-type response-type))
182
#+(or) ; incorrect, post must be a sparql request
183
(:post ((resource |/:account/repositories/:repository|) request response (request-type mime:rdf) response-type)
184
(multiple-value-bind (pathname effective-content-type) (call-next-method)
185
(unwind-protect (progn (graph-store-post-content resource request response pathname effective-content-type)
187
(conditional-delete-file pathname))))
190
;; this approach to create a repository does not work, as it introduces a repository instance
191
;; but fails to authenticate it
192
(:put ((resource |/:account/repositories/:repository|) request response)
193
"create a repository. idempotent"
194
(let ((repository (resource-repository resource)))
195
(dydra:create-repository repository :if-exists nil)
196
(setf (http:response-location response) (request-resource-location request resource))
197
(setf (http:response-etag response) (spocq.i::resolve-repository-revision-id repository))
198
(setf (http:response-status-code response) http:no-content)))
200
;; for ask and select
201
(:get ((resource |/:account/repositories/:repository|) request response (request-type null) (response-type mime:application/sparql-results))
202
(let ((query (http:request-query-argument request "query")))
203
(if (plusp (length query))
204
(graph-store-query resource query request response mime:application/sparql-query (http:response-media-type response))
205
(http:bad-request "The request must include a query."))))
207
;; for queries (construct and describe) and for graph content
208
(:get ((resource |/:account/repositories/:repository|) request response (request-type null) (response-type mime:rdf))
209
(let ((query (http:request-query-argument request "query")))
210
(if (plusp (length query))
211
(graph-store-query resource query request response mime:application/sparql-query (http:response-media-type response))
212
(graph-store-get-graph resource request response request-type response-type))))
214
(:get ((resource |/:account/repositories/:repository|) request response (request-type null) (response-type mime:text/x-graphviz))
215
(let ((query (http:request-query-argument request "query")))
216
(if (plusp (length query))
217
(graph-store-query resource query request response mime:application/sparql-query (http:response-media-type response))
218
(graph-store-get-graph resource request response request-type response-type))))
220
(:get ((resource |/:account/repositories/:repository|) request response (request-type null) (response-type mime:text/csv))
221
(let ((query (http:request-query-argument request "query")))
222
(if (plusp (length query))
223
(graph-store-query resource query request response mime:application/sparql-query (http:response-media-type response))
224
(graph-store-get-graph resource request response request-type response-type))))
226
(:get ((resource |/:account/repositories/:repository|) request response (request-type null) (response-type mime:text/tab-separated-values))
227
(let ((query (http:request-query-argument request "query")))
228
(if (plusp (length query))
229
(graph-store-query resource query request response mime:application/sparql-query (http:response-media-type response))
230
(graph-store-get-graph resource request response request-type response-type))))
233
(:post ((resource |/:account/repositories/:repository|) request response (request-type mime:application/sparql-query) (response-type mime:application/sparql-results))
234
;; given a body with just the query text accept the entire body.
235
(graph-store-query resource (http:request-body request) request response request-type (http:response-media-type response)))
237
(:post ((resource |/:account/repositories/:repository|) request response (request-type mime:application/x-www-form-urlencoded) (response-type mime:application/sparql-results))
238
;; given a form body, decode it ans extract the query
239
(let ((query (http:request-post-argument request "query")))
240
(graph-store-query resource query request response mime:application/sparql-query (http:response-media-type response))))
242
(:post ((resource |/:account/repositories/:repository|) request response (request-type mime:application/sparql-query) (response-type mime:rdf))
243
;; given a body with just the query text accept the entire body.
244
(graph-store-query resource (http:request-body request) request response request-type (http:response-media-type response)))
246
(:post ((resource |/:account/repositories/:repository|) request response (request-type mime:application/x-www-form-urlencoded) (response-type mime:rdf))
247
;; given a form body, decode it ans extract the query
248
(let ((query (http:request-post-argument request "query")))
249
(graph-store-query resource query request response mime:application/sparql-query (http:response-media-type response))))
252
(:delete ((resource |/:account/repositories/:repository|) request response)
253
(http:not-implemented))
255
(:get ((resource |/:account/repositories/:repository/statements|) request response request-type response-type)
256
"Return the repository content which satisfies the contraints.
257
Pass the subject/predicate/object as supplied, but use the interned context from the graph-resource mix-in.
258
If there is no matched content, do not issue a 404, but rather just return no content.
259
in order to support multiple contexts, if the are context arguments, iterate over them and encode each response in turn.
260
If none is provided, then just return the stream from the global match"
261
(let ((graphs (resource-graphs resource)))
263
(loop for graph in graphs
264
for content-stream = (handler-case (graph-store-get-graph resource request response request-type response-type
265
:subject (http:request-query-argument request "subj")
266
:predicate (http:request-query-argument request "pred")
267
:object (http:request-query-argument request "obj")
269
(http:not-found () nil))
271
do (http:encode-response content-stream response(http:response-media-type response)))
272
(handler-case (graph-store-get-graph resource request response request-type response-type
273
:subject (http:request-query-argument request "subj")
274
:predicate (http:request-query-argument request "pred")
275
:object (http:request-query-argument request "obj"))
276
(http:not-found () nil)))))
278
(:post ((resource |/:account/repositories/:repository/statements|) request response request-type response-type)
279
(multiple-value-bind (pathname effective-content-type) (call-next-method)
280
(unwind-protect (progn (unless (resource-graph resource)
281
;; sesame requests w/o a graph do not create a new one
282
;; "The operation is executed on all statements that are in the repository if no context is specified"
283
;; (see http://openrdf.callimachus.net/sesame/2.7/docs/system.docbook?view#repository-statements)
284
(setf (resource-graph resource) |urn:dydra|:|default|))
285
(graph-store-post-content resource request response pathname effective-content-type)
287
(conditional-delete-file pathname))
290
(:put ((resource |/:account/repositories/:repository/statements|) request response request-type response-type)
291
(multiple-value-bind (pathname effective-content-type) (call-next-method)
292
(unwind-protect (progn (graph-store-put-content resource request response pathname effective-content-type)
294
(conditional-delete-file pathname))
297
(:delete ((resource |/:account/repositories/:repository/statements|) request response request-type response-type)
298
"delete repository content, but permit it to be idempotent."
299
(let ((*graph-store-if-empty-condition* 'http:no-content))
300
(graph-store-delete-graph resource request response)
303
(:decode mime:text/plain :as mime:application/n-triples)
305
(:decode ((resource |/:account/repositories/:repository/statements|) request response (request-type mime:rdf) (response-type t))
306
(let* ((repository (resource-repository resource))
307
(pathname (tmp-import-pathname (dydra:repository-account repository) repository))
308
(content-length (http:request-content-length request))
309
(import-limit (spocq.e:import-limit)))
311
(unless (<= content-length import-limit)
312
(http:request-entity-too-large "Content exceeds length limit: ~s." import-limit)))
313
(http:copy-stream (http:request-content-stream request) pathname :length (or content-length import-limit))
314
(values pathname request-type)))
316
(:decode ((resource |/:account/repositories/:repository/statements|) request response (request-type mime:application/trix) (response-type t))
317
"translate trix into nquads"
318
(let* ((repository (resource-repository resource))
319
(pathname (call-next-method))
320
(nq-pathname (tmp-import-pathname (dydra:repository-account repository) repository))
321
(process (unwind-protect (run-program "/opt/dydra/bin/trix2nq" ()
322
:input pathname :output nq-pathname
324
(conditional-delete-file pathname))))
325
(unless (and process (zerop (run-program-exit-code process)))
326
(conditional-delete-file nq-pathname)
327
(http:bad-request "Failed to convert trix content."))
328
(when process (run-program-close process))
329
(values nq-pathname mime:application/n-quads)))
331
(:decode ((resource |/:account/repositories/:repository/statements|) request response (request-type mime:application/rdf+json) (response-type t))
332
"transate rdf+json into nquads"
333
(let* ((repository (resource-repository resource))
334
(pathname (call-next-method))
335
(nq-pathname (tmp-import-pathname (dydra:repository-account repository) repository))
336
(process (unwind-protect (run-program "/opt/dydra/bin/rapper" `("-q" "-i" "json" "-o" "nquads"
337
,(namestring (truename pathname)) "-")
341
(conditional-delete-file pathname))))
342
(unless (and process (zerop (run-program-exit-code process)))
343
(conditional-delete-file nq-pathname)
344
(http:bad-request "Failed to convert json content."))
345
(when process (run-program-close process))
346
(values nq-pathname mime:application/n-quads)))
348
(:decode ((resource |/:account/repositories/:repository/statements|) request response (request-type mime:application/xhtml+xml) (response-type t))
349
"transate application/xhtml+xml as rdfa into nquads. allows for non-standard 'application/xhtml+rdfa'.
350
(see http://www.w3.org/TR/rdfa-in-html/)"
351
(let* ((repository (resource-repository resource))
352
(pathname (call-next-method))
353
(nq-pathname (tmp-import-pathname (dydra:repository-account repository) repository))
354
(process (unwind-protect (run-program "/opt/dydra/bin/rapper" `("-q" "-i" "rdfa" "-o" "nquads"
355
,(namestring (truename pathname)) "-")
359
(conditional-delete-file pathname))))
360
(unless (and process (zerop (run-program-exit-code process)))
361
(conditional-delete-file nq-pathname)
362
(http:bad-request "Failed to convert xhtml+rdfa content."))
363
(when process (run-program-close process))
364
(values nq-pathname mime:application/n-quads)))
366
(:decode ((resource |/:account/repositories/:repository/statements|) request response (request-type mime:text/html) (response-type t))
367
"transate text/html as rdfa into nquads. allows for non-standard 'text/html+rdfa'.
368
(see http://www.w3.org/TR/rdfa-in-html/)"
369
(let* ((repository (resource-repository resource))
370
(pathname (call-next-method))
371
(nq-pathname (tmp-import-pathname (dydra:repository-account repository) repository))
372
(process (unwind-protect (run-program "/opt/dydra/bin/rapper" `("-q" "-i" "rdfa" "-o" "nquads"
373
,(namestring (truename pathname)) "-")
377
(conditional-delete-file pathname))))
378
(unless (and process (zerop (run-program-exit-code process)))
379
(conditional-delete-file nq-pathname)
380
(http:bad-request "Failed to convert text/html content."))
381
(when process (run-program-close process))
382
(values nq-pathname mime:application/n-quads)))
385
(defmethod http.i::log-http-function ((function-name t) (resource repository-resource) (request t) (response t) (content-type t) (accept-type t) (methods t))
387
(format *trace-output* "~%graph:~11t~s" (resource-graphs resource)))
393
(http:def-resource-function sesame-service (resource request response)
396
(:auth http:authenticate-request-password)
397
(:auth http:authenticate-request-token)
398
(:auth http:authenticate-request-session)
399
(:auth http:authenticate-request-location)
401
(:auth http:authorize-request)
403
;; responses are just the rdf document media types
404
(:encode mime:application/trix)
405
(:encode mime:application/rdf+json)
406
(:encode :default mime:application/n-quads)
407
(:encode mime:application/n-triples)
408
(:encode mime:application/ld+json)
409
(:encode mime:application/rdf+xml)
410
(:encode mime:text/turtle)
411
(:encode mime:text/x-graphviz)
413
(:get ((resource |/:account/repositories/:repository/rdf-graphs|) request response request-type response-type)
414
(multiple-value-bind (solutions dimensions)
415
(dydra:sparql-query "SELECT DISTINCT ?contextID WHERE {GRAPH ?contextID {?s ?p ?o}}"
416
:repository (resource-repository resource))
417
(dydra:make-list-solution-field :dimensions dimensions
418
:solutions solutions)))
420
(:get ((resource |/:account/repositories/:repository/rdf-graphs/service|) request response request-type (response-type mime:rdf))
421
(graph-store-get-graph resource request response request-type response-type))
423
(:get ((resource |/:account/repositories/:repository/rdf-graphs/service|) request response request-type (response-type mime:text/x-graphviz))
424
(graph-store-get-graph resource request response request-type response-type))
426
(:post ((resource |/:account/repositories/:repository/rdf-graphs/service|) request response request-type response-type)
427
(multiple-value-bind (pathname effective-content-type) (call-next-method)
428
(unwind-protect (progn (graph-store-post-content resource request response pathname effective-content-type)
430
(conditional-delete-file pathname))))
432
(:put ((resource |/:account/repositories/:repository/rdf-graphs/service|) request response request-type response-type)
433
(multiple-value-bind (pathname effective-content-type) (call-next-method)
434
(unwind-protect (progn (graph-store-put-content resource request response pathname effective-content-type)
436
(conditional-delete-file pathname))))
438
(:delete ((resource |/:account/repositories/:repository/rdf-graphs/service|) request response request-type response-type)
439
(graph-store-delete-graph resource request response))
441
(:get ((resource |/:account/repositories/:repository/rdf-graphs/:graph|) request response request-type (response-type mime:rdf))
442
(graph-store-get-graph resource request response request-type response-type))
444
(:get ((resource |/:account/repositories/:repository/rdf-graphs/:graph|) request response request-type (response-type mime:text/x-graphviz))
445
(graph-store-get-graph resource request response request-type response-type))
447
(:post ((resource |/:account/repositories/:repository/rdf-graphs/:graph|) request response request-type response-type)
448
(multiple-value-bind (pathname effective-content-type) (call-next-method)
449
(unwind-protect (progn (graph-store-post-content resource request response pathname effective-content-type)
451
(conditional-delete-file pathname))))
453
(:put ((resource |/:account/repositories/:repository/rdf-graphs/:graph|) request response request-type response-type)
454
(multiple-value-bind (pathname effective-content-type) (call-next-method)
455
(unwind-protect (progn (graph-store-put-content resource request response pathname effective-content-type)
457
(conditional-delete-file pathname))))
459
(:delete ((resource |/:account/repositories/:repository/rdf-graphs/:graph|) request response (request-type t) (response-type t))
460
(graph-store-delete-graph resource request response))
463
(:decode ((resource |/:account/repositories/:repository/rdf-graphs|) request response (request-type mime:rdf) (response-type t))
464
(let* ((repository (resource-repository resource))
465
(pathname (tmp-import-pathname (dydra:repository-account repository) repository))
466
(content-length (http:request-content-length request))
467
(import-limit (spocq.e:import-limit)))
469
(unless (<= content-length import-limit)
470
(http:request-entity-too-large "Content exceeds length limit: ~s." import-limit)))
471
(http:copy-stream (http:request-content-stream request) pathname :length (or content-length import-limit))
472
(values pathname request-type)))
474
(:decode ((resource |/:account/repositories/:repository/rdf-graphs|) request response (request-type mime:application/trix) (response-type t))
475
"translate trix into nquads"
476
(let* ((repository (resource-repository resource))
477
(pathname (call-next-method))
478
(nq-pathname (tmp-import-pathname (dydra:repository-account repository) repository))
479
(process (unwind-protect (run-program "/opt/dydra/bin/trix2nq" ()
480
:input pathname :output nq-pathname
482
(conditional-delete-file pathname))))
483
(unless (and process (zerop (run-program-exit-code process)))
484
(conditional-delete-file nq-pathname)
485
(http:internal-error "trix to nquad conversion failed."))
486
(when process (run-program-close process))
487
(values nq-pathname mime:application/n-quads)))
489
(:decode ((resource |/:account/repositories/:repository/rdf-graphs|) request response (request-type mime:application/rdf+json) (response-type t))
490
"transate rdf+json into nquads"
491
(let* ((repository (resource-repository resource))
492
(pathname (call-next-method))
493
(nq-pathname (tmp-import-pathname (dydra:repository-account repository) repository))
494
(process (unwind-protect (run-program "/opt/dydra/bin/rapper" `("-q" "-i" "json" "-o" "nquads"
495
,(namestring (truename pathname)) "-")
499
(conditional-delete-file pathname))))
500
(unless (and process (zerop (run-program-exit-code process)))
501
(conditional-delete-file nq-pathname)
502
(http:internal-error "trix to nquad conversion failed."))
503
(when process (run-program-close process))
504
(values nq-pathname mime:application/n-quads)))
506
(:decode ((resource |/:account/repositories/:repository/rdf-graphs|) request response (request-type mime:application/xhtml+xml) (response-type t))
507
"transate application/xhtml+xml as rdfa into nquads. allows for non-standard 'application/xhtml+rdfa'.
508
(see http://www.w3.org/TR/rdfa-in-html/)"
509
(let* ((repository (resource-repository resource))
510
(pathname (call-next-method))
511
(nq-pathname (tmp-import-pathname (dydra:repository-account repository) repository))
512
(process (unwind-protect (run-program "/opt/dydra/bin/rapper" `("-q" "-i" "rdfa" "-o" "nquads"
513
,(namestring (truename pathname)) "-")
517
(delete-file pathname))))
518
(unless (and process (zerop (run-program-exit-code process)))
519
(conditional-delete-file nq-pathname)
520
(http:internal-error "xhtml+rdfa to nquad conversion failed."))
521
(when process (run-program-close process))
522
(values nq-pathname mime:application/n-quads)))
524
(:decode ((resource |/:account/repositories/:repository/rdf-graphs|) request response (request-type mime:text/html) (response-type t))
525
"transate text/html as rdfa into nquads. allows for non-standard 'text/html+rdfa'.
526
(see http://www.w3.org/TR/rdfa-in-html/)"
527
(let* ((repository (resource-repository resource))
528
(pathname (call-next-method))
529
(nq-pathname (tmp-import-pathname (dydra:repository-account repository) repository))
530
(process (unwind-protect (run-program "/opt/dydra/bin/rapper" `("-q" "-i" "rdfa" "-o" "nquads"
531
,(namestring (truename pathname)) "-")
534
(delete-file pathname))))
535
(unless (and process (zerop (run-program-exit-code process)))
536
(conditional-delete-file nq-pathname)
537
(http:internal-error "html+rdfa to nquad conversion failed."))
538
(when process (run-program-close process))
539
(values nq-pathname mime:application/n-quads)))
541
(:decode ((resource |/:account/repositories/:repository/rdf-graphs|) request response (request-type mime:text/plain) (response-type t))
542
"Perform the receive of text/plain request data into a file and return the pathname to
543
be used directly as n-triples"
544
(let* ((repository (resource-repository resource))
545
(pathname (tmp-import-pathname (dydra:repository-account repository) repository))
546
(content-length (http:request-content-length request))
547
(import-limit (spocq.e:import-limit)))
549
(unless (<= content-length import-limit)
550
(http:request-entity-too-large "Content exceeds length limit: ~s." import-limit)))
551
(http:copy-stream (http:request-content-stream request) pathname :length (or content-length import-limit))
552
(values pathname mime:application/n-triples)))