;; TODO: Modify this parameter to match the location of Wilbur on your system. (defparameter *wilbur-location* "/Users/sir03rn/Lisp/wilbur-rdf/") ;; ASDF is needed for loading Araneida and wilbur-ext. (require 'asdf) ;; (require 'araneida) (asdf::operate 'asdf::load-op 'araneida) ;; Pathnames for Wilbur. (setf (logical-pathname-translations "wilbur") `(("core;*.lisp" "wilbur:base;source;*.*") ("core;*.system" "wilbur:base;source;*.*") ("core;*.fasl" "wilbur:bin;*.*") ("core;*.*" "wilbur:base;*.*") ("schemata;*.*" "wilbur:base;schemata;*.*") ("base;**;*.*" ,(concatenate 'string *wilbur-location* "core/**/*.*")) ("bin;**;*.*" ,(concatenate 'string *wilbur-location* "binaries/**/*.*")))) ;; Load Nokia's make and Wilbur itself. (load (concatenate 'string *wilbur-location* "make/mm")) (load (concatenate 'string *wilbur-location* "core/source/wilbur.system")) ;; Make the module. (in-package :cl-user) (make-module :wilbur) ;; Load Richard's Wilbur extensions. (asdf::operate 'asdf::load-op 'wilbur-ext) (defpackage "URIQA" (:shadowing-import-from "ARANEIDA" "URL-PORT" "MAKE-URL" "URL-PATH" "URL-HOST" "HTTP-URL" "URL") (:use "CL" "ARANEIDA" "WILBUR" "WILBUR-EXT" #+openmcl "CCL")) (in-package "URIQA") ;; TODO: do these. (defparameter *access-url* (parse-urlstring "http://localhost:8000/")) (defparameter *mput-prefix* "http://localhost:8000/mput/") (eval-when (:compile-toplevel :load-toplevel :execute) ;; This is for using Araneida behind a reverse-proxying ;; Apache (or other HTTP proxy) server. You may need to alter the ;; configuration for your local setup #+nil (pushnew :araneida-uses-proxy *features*) ;; if you have a threaded SBCL, and want to, you can use the (new, ;; whizzy) thread-based server instead of the (older, better tested) ;; SERVE-EVENT thing #+araneida-threads (pushnew :araneida-uses-threads *features*)) ;; ARANEIDA: #-araneida-uses-proxy (defvar *listener* (make-instance #+araneida-uses-threads 'araneida::threaded-http-listener #-araneida-uses-threads 'araneida::serve-event-http-listener :port (araneida::url-port *access-url*))) #+araneida-uses-proxy (defvar *listener* (let ((fwd-url (araneida::copy-url *access-url*))) (setf (araneida::url-port fwd-url) (+ 1024 (araneida::url-port *access-url*))) (make-instance #+araneida-uses-threads 'araneida::threaded-reverse-proxy-listener #-araneida-uses-threads 'araneida::serve-event-reverse-proxy-listener :translations `((,(araneida::urlstring *access-url*) ,(araneida::urlstring fwd-url))) :address #(0 0 0 0) :port (araneida::url-port fwd-url)))) ;; Setup Wilbur. (setf wilbur::*db* (make-instance 'wilbur::db :emptyp t)) (defclass uriqa-handler (handler) ()) (defclass uriqa-query-handler (handler) ()) ;; From rdf-serialiser.lisp ;; TODO: refactor. (defgeneric serialise (d str out-format)) (defun s-append (s p o) (format nil "~A ~A ~A ." s p o)) ;;; These will soon be replaced by Wilbur2's serialiser. (defmethod serialise (d str (out-format (eql 'label-html))) (if (typep d 'wilbur::db) (format str "
| Subject | Property | Object |
|---|
| Subject | Property | Object |
|---|
Enter a URI below.
You may also use the following HTTP verbs:
You might also find the query interface useful. This is described more fully at the URIQA page.
") "Welcome to the URIQA server.")) ;;; GET handler. ;;; "A URIQA enlightened server should attempt to provide a description of a ;;; resource when a general GET request fails." --- so we do. (defmethod handle-request-response ((handler uriqa-handler) (method (eql :get)) request) (let ((target-url (urlstring (request-url request))) (uri-header (car (request-header request :uriqa-uri)))) (let ((target-node (if (and uri-header (test-prefix target-url uri-header)) (node uri-header) (node target-url)))) (if (and target-node (not (string= "" (request-unhandled-part request)))) (progn (request-send-headers request :content-type "application/rdf+xml") (serialise (cbd target-node) (request-stream request) 'rdf-xml)) (progn (request-send-headers request :content-type "application/xhtml+xml") (format (request-stream request) *default-page*))) t))) ;;; MGET handler. Return a CBD for the target resource. ;;; This also accepts the URIQA-uri: header. (defmethod handle-request-response ((handler uriqa-handler) (method (eql :mget)) request) (let ((target-url (urlstring (request-url request))) (uri-header (car (request-header request :uriqa-uri)))) (let ((target-node (if (and uri-header (test-prefix target-url uri-header)) (node uri-header) (node target-url)))) (request-send-headers request) (serialise (cbd target-node) (request-stream request) 'rdf-xml) t))) ;;; MPUT handler. (defmethod handle-request-response ((handler uriqa-handler) (method (eql :mput)) request) (let ((subject-url (urlstring (request-url request))) (uri-header (car (request-header request :uriqa-uri))) (body-text (request-body request))) ;; Note that we don't actually CARE about the URI! ;; This just adds RDF to the store! (let ((target-node (if (and uri-header (test-prefix subject-url uri-header)) (node uri-header) (node subject-url)))) (if (and target-node body-text) (let ((parsed-body (wilbur-ext::rdf->db body-text (make-unique-uri *mput-prefix*)))) (if parsed-body (progn (db-merge *db* (db-merge *db* (cbd target-node parsed-body))) (request-send-headers request) (format (request-stream request) "RDF added to store.~%") t) (request-send-error request 400 "Error: no valid body was provided to MPUT.~%"))) (request-send-error request 400 (format nil "Error: ~A~A~A~%" (if target-node "" "no target node") (if (and target-node (not body-text)) ", ") (if body-text "." "no body."))))))) ;;; MDELETE handler. (defmethod handle-request-response ((handler uriqa-handler) (method (eql :mdelete)) request) (let ((subject-url (urlstring (request-url request))) (uri-header (car (request-header request :uriqa-uri))) (body-text (request-body request))) (let ((target-node (if (and uri-header (test-prefix subject-url uri-header)) (node uri-header) (node subject-url)))) (if (nodep target-node) (let ((parsed-body (if (stringp body-text) (wilbur-ext::rdf->db body-text (make-unique-uri *mput-prefix*))))) (if parsed-body (progn (format t "Deleting provided CBD for ~A.~%" target-node) ;; Either remove just the triples in the union of the CBD ;; and the supplied body... (remove-triples (cbd target-node parsed-body) *db*)) ;; ... or remove the whole CBD. (delete-cbd target-node *db*)) t) (request-send-error request 400 (format nil "Error: no target node.~%")))))) (install-handler (araneida::http-listener-handler *listener*) (make-instance 'uriqa-handler) (araneida::urlstring (araneida::merge-url *access-url* "")) nil) (install-handler (araneida::http-listener-handler *listener*) (make-instance 'uriqa-query-handler) (araneida::urlstring (araneida::merge-url *access-url* "uriqa")) nil) (start-listening *listener*)