Skip to content

Instantly share code, notes, and snippets.

@archimag
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save archimag/cc2d2fe8cf26cbae0095 to your computer and use it in GitHub Desktop.
Save archimag/cc2d2fe8cf26cbae0095 to your computer and use it in GitHub Desktop.
RESTAS Demo
;; restas-demo.lisp
;;
;; Данное приложение демонстрирует некоторые возможности работы с RESTAS:
;; * Работа с request
;; * Работа с reply
;; * Работа с cookies
;; * Редирект
;; * Отдача файлов
;; * Возвращение promise из маршрута
;;
;; Данные возможности должны быть идентичны для Hunchentoot, так и для Wookie.
;; Исключения:
;; * Возврата promise из маршрута допускается только в Wookie
;; * Функция abort-route-handler в restas.wookie немедленно отправляет ответ, но
;; не прерывает поток исполнения (в отличие, от restas.hunchentoot)
;;
;; Используйте JSONView для работы с приложением в браузере
;; Firefox: http://jsonview.com/
;; Chrome: https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc
;;
;; Другое хорошее расширения для тестирования приложения - Postman
;; Chrome: https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm
;;
;; Следующие библиотеки необходимо устанавливать с github вручную:
;; RESTAS: https://github.com/archimag/restas, ветка - async
;; Wookie: https://github.com/orthecreedence/wookie
;; restas-directory-publisher: https://github.com/archimag/restas-directory-publisher, ветка - async
;; blackbrid: https://github.com/orthecreedence/blackbird
;; cl-walker: https://github.com/archimag/cl-walker
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Грузим необходимые библиотеки
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(ql:quickload "restas.wookie")
(ql:quickload "restas.hunchentoot")
(ql:quickload "restas-directory-publisher")
(ql:quickload "blackbird")
(ql:quickload "cl-json")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Определяем модуль/пакет для нашего приложения
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(restas:define-module #:restas.demo
(:use #:cl #:iter #:alexandria)
(:renderer #'json:encode-json-plist-to-string)
(:content-type "application/json"))
(in-package #:restas.demo)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Навигация
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun navigation ()
(list :index-page (restas:genurl* 'index)
:request-info (restas:genurl* 'request-info :foo "x" :bar "y")
:cookies (plist-alist
(list :install-cookies (restas:genurl* 'install-cookies)
:uninstall-cookies (restas:genurl* 'remove-cookies)))
:promise-example (restas:genurl* 'promise-example)
:external-format-cp1251 (restas:genurl* 'external-format-cp1251)
:source (plist-alist
(list :view-source-by-readfile (restas:genurl* 'source-by-readfile)
:view-source-by-pathname (restas:genurl* 'source-by-pathname)))
:template-variables (restas:genurl* 'template-variables
:digit 1
:name "Hello"
:type "txt")
:browse-home-dir (restas:genurl* '-homedir-.route :path '(""))))
(restas:define-route index ("/")
(navigation))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Информация о параметрах запроса
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(restas:define-route request-info ("/request")
(list :script-name (restas:script-name)
:query-string (restas:query-string)
:get-parameters (restas:get-parameters)
:post-parameters (restas:post-parameters)
:headers-in (restas:headers-in)
:cookies-in (restas:cookies-in)
:authorization (multiple-value-list (restas:authorization))
:remote-address (restas:remote-address)
:remote-port (restas:remote-port)
:host (restas:request-host)
:request-uri (restas:request-uri)
:method (restas:request-method)
:server-protocol (restas:server-protocol)
:user-agent (restas:user-agent)
:referer (restas:referer)
:navigation (plist-alist (navigation))))
(restas:define-route request-info/post ("/request" :method :post)
(request-info))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Работа с cookie
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(restas:define-route install-cookies ("/cookies/install")
(restas:set-cookie "a" :value "Hello world" :path "/")
(restas:set-cookie "b" :value "Goodnight!" :path "/")
(restas:redirect 'request-info))
(restas:define-route remove-cookies ("/cookie/uninstall")
(iter (for (name . nil) in (restas:cookies-in))
(restas:set-cookie name :expires 0 :path "/"))
(restas:redirect 'request-info))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Возврат promise
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(restas:define-route promise-example ("/promise/")
(:decorators 'restas.wookie:@keep-context)
#|==========================================================================|#
(flet ((delay (msg)
(bb:with-promise (resolve reject)
(as:with-delay (3)
(resolve msg)))))
#|------------------------------------------------------------------------|#
(bb:alet ((msg (delay "Hello world")))
(list :text msg
:navigation (plist-alist (navigation))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; external-format
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(restas:define-route external-format-cp1251 ("/external-format/cp1251")
(:content-type "text/plain")
#|==========================================================================|#
(setf (restas:reply-external-format)
:cp1251)
#|--------------------------------------------------------------------------|#
"Привет мир!")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Просмотр исходного кода данного файла
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defparameter *source-path* *load-pathname*)
(restas:define-route source-by-readfile ("/source/read-file")
(:content-type "text/plain")
#|==========================================================================|#
(read-file-into-string *source-path*))
(restas:define-route source-by-pathname ("/source/pathname")
*source-path*)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Пример переменных в шаблоне
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(restas:define-route template-variables ("/:digit/:(name).:(type)")
(:variables (digit #'parse-integer)
(name #'string-upcase))
#|==========================================================================|#
(format nil "[~A] ~A - ~A" digit name type))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Исследование домашней директории
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(restas:mount-module -homedir- (#:restas.directory-publisher)
(:url "/home/")
(restas.directory-publisher:*directory* (user-homedir-pathname))
(restas.directory-publisher:*autoindex* t))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Запуск веб-серверов
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(restas.wookie:start '#:restas.demo :port 8080)
(restas.hunchentoot:start '#:restas.demo :port 8088)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment