Implement a basic, bare-bones inbox!

Adding a new interface, the RECEIVE method.
This allows objects to be received on the inbox,
however sans signature validation.
This commit is contained in:
Jaidyn Ann 2024-12-09 22:25:35 -06:00
parent 233a76d571
commit 380bc3f525
2 changed files with 27 additions and 5 deletions

View File

@ -27,6 +27,9 @@
(defvar *store* (make-hash-table :test #'equal) (defvar *store* (make-hash-table :test #'equal)
"Our “object-store” — stores all ActivityPub objects, mapped by their IRI @ID.") "Our “object-store” — stores all ActivityPub objects, mapped by their IRI @ID.")
(defvar *inbox* nil
"Our inbox, a simple list containing all received objects.")
(defvar *config* (defvar *config*
'(:host "http://localhost:8080" :address "0.0.0.0" :port 8080 :fetch fetch)) '(:host "http://localhost:8080" :address "0.0.0.0" :port 8080 :fetch fetch))
@ -60,13 +63,19 @@ For example: “https://localhost:8080/users/lena”.")
;;; Activity-Servist callbacks ;;; Activity-Servist callbacks
;;; ———————————————————————————————————————— ;;; ————————————————————————————————————————
(defun fetch (uri) (defun fetch (uri)
"activity-servist callback: Returns the JSON-LD-OBJECT of the given @ID or URI "activity-servist callback: Returns the JSON-LD OBJECT of the given @ID or URI
from our object-store. from our object-store.
This example server simply stores objects in a hash-table mapping IDs to objects." This example server simply stores objects in a hash-table mapping IDs to objects."
(let ((id (or (uri->id uri) uri))) (let ((id (or (uri->id uri) uri)))
(gethash id *store*))) (gethash id *store*)))
(defmethod as:receive ((obj json-ld:object))
"activity-servist callback: Recieve a JSON-LD OBJECT (posted to the server's
inbox, and decide what to do with it!"
(setq *inbox* (append *inbox* (list obj))))
;;; ID-management ;;; ID-management
;;; ———————————————————————————————————————— ;;; ————————————————————————————————————————

View File

@ -21,6 +21,8 @@
(:export (:export
;; Functions ;; Functions
:server :start-server :server :start-server
;; Methods
:receive
;; Globals ;; Globals
*config*)) *config*))
@ -75,6 +77,15 @@ Returns the ActivityPub object associated with the given URI."
(funcall func uri) (funcall func uri)
(error "No FETCH function found in ACTIVITY-SERVIST:*CONFIG*.")))) (error "No FETCH function found in ACTIVITY-SERVIST:*CONFIG*."))))
(defgeneric receive (obj)
(:documentation
"Called when an OBJECT is sent to activity-servists HTTP inbox.
This is done by other servers, and is how activities and objects get federated
with ActivityPub.
To receive objects, you should overload this generic with (at the bare minimum)
a method accepting JSON-LD:OBJECTs. Doing so is required not defining this
method will cause an error when an object is sent to the inbox."))
;;; Host-info response ;;; Host-info response
@ -145,9 +156,11 @@ can be found). Uses the callback :FETCH, defined in *CONFIG*."
;;; Inbox requests ;;; Inbox requests
;;; ———————————————————————————————————————— ;;; ————————————————————————————————————————
(defun http-inbox (env path-items params) (defun http-inbox (env path-items params)
(let* ((raw-contents (alexandria:read-stream-content-into-byte-vector (getf env :raw-body))) "If one tries to send an activity to our inbox, pass it along to
(contents (babel:octets-to-string raw-contents))) the overloaded RECEIVE method."
'(400 (:content-type "text/plain") ("You tried!")))) (let* ((contents (body-contents (getf env :raw-body))))
(receive (json-ld:parse contents))
'(200 (:content-type "text/plain") ("You win!"))))
@ -228,7 +241,7 @@ can be found). Uses the callback :FETCH, defined in *CONFIG*."
;;; ———————————————————————————————————————— ;;; ————————————————————————————————————————
(defun server (env) (defun server (env)
"Returns the response data for Clack, given the request property-list ENV." "Returns the response data for Clack, given the request property-list ENV."
(setq *logs* (append *logs* (list env (body-contents (getf env :raw-body))))) (setq *logs* (append *logs* (list env)))
(let* ((path (pathname-sans-parameters (getf env :request-uri))) (let* ((path (pathname-sans-parameters (getf env :request-uri)))
(params (pathname-parameters (getf env :request-uri))) (params (pathname-parameters (getf env :request-uri)))
(response-function (response-function