;; disfluid, implementation of the Solid specification ;; Copyright (C) 2021 Vivien Kraus ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU Affero General Public License as ;; published by the Free Software Foundation, either version 3 of the ;; License, or (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU Affero General Public License for more details. ;; You should have received a copy of the GNU Affero General Public License ;; along with this program. If not, see . (define-module (webid-oidc serve) #:use-module (webid-oidc errors) #:use-module (webid-oidc fetch) #:use-module (webid-oidc web-i18n) #:use-module ((webid-oidc parameters) #:prefix p:) #:use-module (ice-9 optargs) #:use-module (ice-9 receive) #:use-module (ice-9 exceptions) #:use-module (rnrs bytevectors) #:use-module (web request) #:use-module (web response) #:use-module (web uri) #:use-module (rdf rdf) #:use-module (turtle fromrdf) #:use-module (nquads fromrdf) #:use-module (json) #:use-module (jsonld) #:declarative? #t #:export ( ¬-acceptable make-not-acceptable not-acceptable? not-acceptable-client-accepts not-acceptable-path not-acceptable-content-type convert )) (define-exception-type ¬-acceptable &external-error make-not-acceptable not-acceptable? (client-accepts not-acceptable-client-accepts) (path not-acceptable-path) (content-type not-acceptable-content-type)) (define (convert client-accepts server-name path content-type content) (let ((data-as-rdf (false-if-exception (parameterize ((p:anonymous-http-request (lambda _ (values (build-response #:headers `((content-type ,content-type))) content)))) (fetch (build-uri (uri-scheme server-name) #:userinfo (uri-userinfo server-name) #:host (uri-host server-name) #:port (uri-port server-name) #:path path)))))) (if client-accepts ;; Content negociation is asked (let try-satisfy ((accepts client-accepts)) (if (null? accepts) (let ((final-message (format #f (G_ "content negociation failed while serving a request")))) (raise-exception (make-exception (make-not-acceptable client-accepts path content-type) (make-exception-with-message final-message)))) (let ((request (car accepts))) (cond ((or (eq? request content-type) (eq? request '*/*)) (values content-type content)) ((and (eq? request 'text/turtle) data-as-rdf) (values 'text/turtle (rdf->turtle data-as-rdf))) ((and (or (eq? request 'application/n-quads) (eq? request 'text/x-nquads)) data-as-rdf) (values request (rdf->nquads (make-rdf-dataset data-as-rdf '())))) ((and (eq? request 'application/ld+json) data-as-rdf) (values 'application/ld+json (scm->json-string (rdf->jsonld (make-rdf-dataset data-as-rdf '()))))) ;; Add other conversion strategies here (else (try-satisfy (cdr accepts))))))) ;; Content negociation is unwanted (values content-type content))))