RadianceはWebアプリケーション環境であり、Webフレームワークのようなものですが、より一般的で柔軟です。個人的なウェブサイトや一般的に展開可能なアプリケーションを簡単に展開できるようにし、特別な適応を受けることなく、実質的にあらゆるセットアップで使用できるようにすることができます。
放射輝度と関連するモジュールとアプリケーションは、QuickLispを介して別のdistで配布されます。輝きをインストールするには、次のことを行います。
(ql-dist:install-dist "http://dist.shirakumo.org/shirakumo.txt")
(ql:quickload :radiance)
そこからOn Outは、QuickLispのquickloadを介してPurplishのようなあらゆる種類の輝きモジュールを直接ロードして使用できるはずです。
Radianceと重要な概念のほとんどを紹介するチュートリアルを見つけることができ、ここでWebアプリケーションを一般的に書く方法を探ります。それはあなたに物事を進める方法について良い感覚を与え、あなたが特定の機能が必要な場合にどこを見るべきかについての指針を与えるはずです。最後の部分では、実際のセットアップと生産サーバーへの輝きのインストールの展開にも入ります。
あなたがやりたいと思う最も基本的なことは、ある種のHTMLを提供することです。それでは、それに向かって取り組み、徐々に拡張しましょう。始める前に、輝きを始める必要があります。
( ql :quickload :radiance )
( radiance :startup) Radianceのセットアップが初めての場合、 r-welcomeモジュールを使用してメモを取得できます。また、ブラウザで開いて小さなグリーティングページを表示できるリンクも提供する必要があります。とりあえず、私たちはそれに沿って自分の小さなページを立てたいだけです。
( in-package :rad-user )
(define-page example " /example " ()
( setf (content-type *response* ) " text/plain " )
" Hi! " )LocalHostにアクセスする:8080/例は、「こんにちは」を表示するだけです。むしろむしろ退屈です。代わりにHTMLを吐き出しましょう。今のところ、非常に簡単なので、CL-Whoを使用します。最初にクイックロードしてから、次を実行します。
(define-page example " /example " ()
( cl-who :with-html-output-to-string (o)
( cl-who :htm
( :html
( :head ( :title " Example Page " ))
( :body ( :header ( :h1 " Couldn't Be Simpler. " ))
( :main ( :p " Trust me on this one. " )))))))後で再コンパイルして更新すると、いくつかのフォントスタイリングが行われています。次に、おそらくCSSファイルを追加して適切にスタイリングする必要があります。別のページを使用してCSSを提供することもできますが、それは長期的に物事を進めるための最良の方法ではありません。
代わりに、モジュールの作成方法を見てみましょう。これにより、より整然とした方法で物事を整理できます。モジュールのファイルを手動で作成できますが、今のところ、Radianceが提供できる自動的に生成されたスケルトンで解決します。
(create-module " example " )モジュールが存在するパスを返す必要があります。 ASDFシステム、メインのLISPファイル、および2つのフォルダー、 staticおよびtemplateを含める必要があります。驚くべきことに、 staticフォルダーは静的に提供されるファイルが進む場所であり、テンプレートシステムを使用する場合、 templateテンプレートドキュメント用です。
example.lispを開いて、それから例を掲載しましょう。
(define-page example " /example " ()
( cl-who :with-html-output-to-string (o)
( cl-who :htm
( :html
( :head ( :title " Example Page " ))
( :body ( :header ( :h1 " Couldn't Be Simpler. " ))
( :main ( :p " Trust me on this one. " )))))))ページは名前シンボルで識別されます。現在、独自のモジュール、したがって独自のパッケージを持っているため、上記の例のシンボルは以前に使用したものと同じではありません。衝突を避けるために、 rad-userパッケージのページを削除するだけです。
(remove-page ' rad-user::example)変更が有効になるように今すぐ変更するたびに、サンプルファイルをロードしてください。次に、シンプルなCSSファイルを作成して、物事を少しスプルースします。ファイルは、 staticフォルダーにexample.cssに配置されます。自分で書きたくない場合は、サンプルCSSです。
body {
font-family : sans-serif;
font-size : 12 pt ;
background : # EEE ;
}
header {
text-align : center;
}
main {
width : 800 px ;
margin : 0 auto 0 auto;
background : # FFF ;
padding : 10 px ;
border : 1 px solid # BBB ;
border-radius : 5 px ;
}次に、HTMLを変更して、実際にスタイルシートにリンクする必要があります。 StyleSheetに住所を取得するには、Radianceのルーティングシステムを利用する必要があります。心配しないでください、それはあまり面倒ではありません。
(define-page example " /example " ()
( cl-who :with-html-output-to-string (o)
( cl-who :htm
( :html
( :head ( :title " Example Page " )
( :link :rel " stylesheet " :type " text/css "
:href (uri-to-url " /static/example/example.css " :representation :external )))
( :body ( :header ( :h1 " Couldn't Be Simpler. " ))
( :main ( :p " Trust me on this one. " )))))))ページをリフレッシュしてください、そして今、それはそれにいくつかのピザもあります。おそらく、 uri-to-urlビジネス全体の説明が必要です。それを完全に説明することは、これに続くセクションによって処理されますが、その要点は、静的ファイルへのリンクがセットアップの下で適切に解決されることを保証することです。
Radianceの最も中心的な概念の1つは、URIの概念です。 URIは、ドメインのリスト、オプションのポート番号、パス( uriを参照)で構成されるオブジェクトです。それは本質的に一般的なURIの剥ぎ取られたバージョンであるため、スキーマ、クエリ、またはフラグメントパーツは含まれていません。もう1つの重要な違いは、 domains URIがフレームワーク全体のいくつかのポイントで使用され、場所をキャプチャし、ディスパッチマッチングを処理するために使用されることです。
urisは可変であることに注意してください。これは、URIの変更が重要な経路にあるいくつかの部分で起こらなければならないため、パフォーマンスにとって重要です。ただし、通常の場合は、URIがいくつかの選択関数の外部で変更されることは予想されません。 URIの部分を予想外の方法で変更すると、奇妙な行動につながる可能性があります。
urisには一意の文字列表現があり、弦にシリアル化され、再び完全なURIオブジェクトに戻ることができます。 URISはリテラルとしてFASLファイルにダンプすることもできるため、マクロからそれらをエミストすることは問題ありません。 URIの構文は次のとおりです。
URI ::= DOMAINS? (':' PORT)? '/' PATH?
DOMAINS ::= DOMAIN ('.' DOMAIN)*
DOMAIN ::= ('a'..'Z' | '0'..'9' | '-')
PORT ::= ('0'..'9'){1, 5}
PATH ::= .*
uri-to-urlを使用して、URIをコンクリートURLに変えることができます。すべての部品の反転、エンコード、および適切なフォーマットは、そこに自動的に処理されます。
uri 、 domains 、 port 、 path 、 matcher 、 uri-string 、 make-uri 、 make-url 、 ensure-uri URI、 copy-uri 、 parse-uri 、 uri< 、 uri> 、 uri= 、 uri-matches 、 merge-uris 、 represent-uri 、 uri-to-url参照してください。
送信されるデータを往復するデータをカプセル化するために、リクエスト( request )と応答( response )オブジェクトのアイデアがあります。リクエストオブジェクトは、リクエストがどの場所にあるかを表すURIを保持し、HTTPペイロードに含まれるすべてのデータは、Post、Get、Header、およびCookie変数などのようなものです。応答オブジェクトには、リターンコード、ヘッダー、Cookie、および実際のボディデータが保持されます。
リクエストの処理中、これらの2つのオブジェクトは常に存在し、 *request*および*response*変数に拘束する必要があります。彼らは、動的ページを生成するために必要な非常に重要な多くの情報をカプセル化します。さらに、リクエストには、任意のデータを保存できる不透明なdataテーブルが含まれています。これは、リクエスト実行中に到達する可能性のあるシステムの個々の部分間で情報を交換する必要がある場合に役立ちます。
要求は、必ずしもHTTPサーバーから来る必要はありません。物事をテストするために、自分でリクエストを作成し、プログラムで送信することもできます。いずれにせよ、リクエストをディスパッチするための主要なインターフェイスはrequestと呼ばれます。これにより、リクエストと応答オブジェクトが作成され、URIが適切に処理されます。自分でそれを行い、完全な要求オブジェクトを実際に送信するだけの場合は、 execute-requestを使用できます。
リクエストの実際の処理については、ディスパッチャー、ページ、およびAPIエンドポイントを参照してください。
*request* 、 *response* 、 *default-external-format* 、 *default-content-type* 、 request 、 uri 、 http-method 、 body-stream 、 headers 、 post-data 、 get-data 、 cookies 、 user-agent 、 referer 、 domain 、 remote 、 data data issue-time 、 response 、 return-code 、 headers 、 content-type 、 cookies 、 cookie 、 external-format name value 、 domain 、 path 、 expires 、 http-only 、 secure 、 cookie-header 、 cookie 、クッキー、 get-var 、 post-var 、 post/get 、 header 、 file 、 redirect 、 serve-file 、 request-run-time 、 *debugger* 、 handle-condition 、 render-error-page 、 execute-request 、 set-data 、 request
リクエストを発送する前に、ルーティングシステムと呼ばれるものを通過します。 「ルート」がリクエストを処理するものを「ルート」とは異なり、Radianceではルート( route )はURI翻訳者の形式です。システムのこの部分は、内部と外部の2つの「宇宙」を作成して支持する責任があるものです。
内部ユニバースは、実際のWebアプリケーションが住んでいるものです。外部宇宙は、HTTPサーバーとWebサイトのユーザーが住んでいるものです。この区別は、片手で、サーバーの潜在的なセットアップがある時点で見えるかもしれないことを心配することなくWebアプリケーションを書くことができるようにするために必要です。アプリケーションを実行するためにどのようなドメイン、ポート、パスセットアップが必要かを心配する必要はありません。一方、WebAdminとして、物事を壊すことを恐れることなく、システムを正確な欲求に合わせてカスタマイズして実行できます。
これはすべて、マッピングと反転ルートの2つの種類があるルートによって促進されます。マッピングルートは、URIを外部宇宙から内部宇宙の1つに変える責任があります。通常、これには、トップレベルのドメインを削減し、おそらくサブドメインのマッピングを行うことが含まれます。反転ルートは反対のことを行います - それらは内部宇宙から外部に移動します。これは、提供されたページにリンクを作成するために必要です。実際に外部からアクセスできるリソースを参照してください。通常、これにはサブドメインマッピングを逆にし、トップレベルのドメインを再度追加することが含まれます。
ルートは任意の作業を実行できます。最も基本的なレベルでは、それらは単にURIを何らかの形で変更する関数です。これにより、管理者としてのすべてのニーズに対応するのに十分なほど強力な非常に柔軟なシステムを作成できます。アプリケーションライターとして、ページに入れたすべてのリンクでexternal-uriまたはuri-to-urlを使用することを確認する必要があります。
route 、 name 、 direction 、 priority 、 translator 、 route 、ルート、 remove-route 、 list-routes define-route 、 define-matching-route 、 define-target-route 、 define-string-route 、 internal-uri 、 external-uriを参照してください
最後に、リクエストのために実際にコンテンツを生成する部分に来ます。 URIディスパッチャは、名前、関数、優先事項をもたらすURIのサブクラスです。リクエストが届くたびに処理される優先順位のあるリストにライブがあります。リクエストのURIは、各ディスパッチャーと一致します。次に、一致する最初のディスパッチャーの機能が実行されます。
そしてそれだけです。ディスパッチャーの関数は、ページコンテンツを配信するために応答オブジェクトに必要な値を設定する責任があります。これを行うために、応答オブジェクトのdataフィールドを直接設定するか、関数から適切な値を返すことができます。 Radianceは、 stream 、 pathname 、 string 、および(array (unsigned-byte 8)) 4種類の値のみを受け入れます。
URIディスパッチャーに明示的な優先順位数がない場合、他の優先度はURIの特異性によって決定されます。これがどのように計算されるかについての説明については、URIソート機能uri>参照してください。
uri-dispatcher 、 name 、 dispatch-function 、 priority 、 uri-dispatcher 、 remove-uri-dispatcher 、 list-uri-dispatchers 、 uri-dispatcher> 、 define-uri-dispatcher 、 dispatch参照してください
ページは、実際のコンテンツサービス機能を定義するために使用する可能性が高いものです。ただし、ページは、定義マクロにいくつかの追加の機能を備えたURI-Dispatcherであり、物事を簡単にします。最も顕著なのは、以下の説明を見つけることができる拡張可能なオプションです。
Radiance自体によって設定されたデフォルトページがいくつかあります。まず、 faviconとrobotsページがあります。これは、Radianceのstatic/ディレクトリからそれぞれのファイルを提供するだけです。おそらく、そのために独自のページを提供するか、本番サーバーでファイルを更新することをお勧めします。
次に、すべてのWebアプリケーションとモジュールに静的なコンテンツを提供する責任があるstaticページがあります。任意のドメインでアクティブであり、常にパス/static/...でアクティブにする必要があります。ここで...最初のディレクトリがモジュールの名前であり、残りはそのモジュールのstatic/ディレクトリ内のパスである必要があります。これにより、一般的なパスを介してCSS、JS、画像などの静的ファイルを常に参照できます。
最後に、 apiページがあります。これは、次のセクションで説明するAPIエンドポイントのディスパッチを処理する責任があります。ページは、すべてのドメインで/api/...パスをキャプチャすることにより、静的なページと同様に動作します。
page 、 remove-page 、 define-pageを参照してください
Radianceは、REST API定義の統合サポートを提供します。これは単なる機能だけでなく、ほとんどの最新のアプリケーションがある種のAPIを提供したいと考えているため、Radianceは必然的にAPIエンドポイントを含むアプリケーションを作成する特定の方法をアドバイスしているためです。
概念的には、APIエンドポイントは、ブラウザリクエストを通じて呼び出す機能です。その後、彼らの応答は、要求者が読み取ることができる形式にシリアル化されます。ただし、覚えておくことは、APIエンドポイントをユーザーとプログラムの両方が使用できるようにする必要があることです。通常、APIを介してプログラムで実行できるあらゆる種類のアクションも、何らかの方法でユーザーが実行する必要があるため、これを奨励します。重複を避けるために、2つは混同することができます。
そのため、通常、ユーザーまたはアプリケーションが要求するかどうかによってわずかに異なる反応をするAPIエンドポイントを介して、あらゆる種類のデータ変更アクションを提供する必要があります。ユーザーの場合、通常、適切なページにリダイレクトする必要があり、アプリケーションの場合は、読み取り可能な形式でデータペイロードを提供する必要があります。
これらすべての最初の部分は、特定の形式へのデータをシリアル化することを担当するAPI形式システムです。デフォルトでは、S-Expressionベースの形式のみが提供されますが、JSON出力を取得するための貢献を簡単にロードできます。
2番目の部分は、 browser投稿/取得パラメーターの仕様です。そのパラメーターに正確な文字列"true"が含まれている場合、API要求はユーザーから来るものとして扱われるため、データペイロードではなくリダイレクトを出力する必要があります。
適切に統合されたAPIを提供するために、アプリケーションがそれらのものを利用する必要があります。これで、実際のエンドポイント定義は、名前、生の関数、関数の引数を説明するラムダリスト、および要求解析機能で構成されています。通常、あなたの議論のために、必要なだけでオプションの議論が理にかなっています。結局のところ、HTTPリクエストには、提供できる「キーワード引数」のみがあり、それらは存在または欠落している可能性があります。
APIエンドポイントの名前は、どこに到達できるかを示す識別子としても機能します。 APIエンドポイントは/api/パスでライブ、エンドポイントの名前が続きます。そのため、他のエンドポイントを誤ってつまずくのを避けるために、モジュールまたはアプリケーションの名前でエンドポイントをプレフィックスする責任があります。これは、APIのエンドポイントが正確に一致し、パスのあいまいさや処理を許可しないでください。これはURIディスパッチャーとは異なります。したがって、すべてのエンドポイントには一意のパスが必要であり、すぐに名前として機能することもできます。
生の関数は、APIがインターフェイスを提供する関数です。要求されたアクションを実行し、上記のように適切なデータを返す責任があります。フォーマットされたAPIデータを返すことについては、 api-output参照してください。ブラウザリクエストの場合のリダイレクトについては、 redirect参照してください。
最後に、リクエスト解析機能は、要求オブジェクトを取得し、関数が必要とする引数を抽出し、最終的に適切な引数でその関数を呼び出すことに責任があります。解析機能は、必要な引数が欠落している場合api-argument-missingエラーを示す場合があります。余分な議論は無視されるべきです。
また、 call-apiを使用してAPIエンドポイントをプログラム的に呼び出すか、URIディスパッチメカニズム全体を実行することなく、 call-api-requestでリクエストコールをシミュレートすることもできます。
ページと同様に、APIエンドポイント定義は、定義をより簡単にする拡張可能なオプションも受け入れます。オプションの説明については、次のセクションを参照してください。
api 、 *default-api-format* 、 *serialize-fallback* 、 api-format 、 remove-api-format 、 list-api-formats 、 define-api-format 、 api-output 、 api-serialize 、 remove-api-endpoint api-endpoint 、remove-api- handler 、 name - api-endpoint list-api-endpoints 、api- request-handler 、 call-api-request argslist call-api 、 define-api
オプションは、拡張可能な定義マクロを提供する方法です。これは、フレームワークが何かを定義する共通の方法を提供する場合に役立ちますが、他の部分は、共通の操作を短くするために拡張機能を提供したい場合があります。たとえば、一般的なタスクは、必要なアクセス資格情報を持っている人にページまたはAPIエンドポイントを制限することです。
これを容易にするために、Radianceはかなり一般的なオプションメカニズムを提供します。オプションは、オプションが属する定義マクロに指定するオプションタイプによって分割されます。 Radianceは、 apiおよびpageオプションタイプを箱から出して提供します。
各オプションには、オプションタイプに応じて、多くの引数を受け入れる必要がある名前のキーワードとエキスパンダー関数があります。常に引数として提供されるのは、定義されているものの名前、定義の身体形式のリスト、およびオプションリストのオプションに提供された最終的なオプションの値です。この膨張関数は、何らかの形で定義マクロの体形態を変換する責任があります。また、何らかの方法で環境をセットアップできるように、定義自体の外側に配置された2番目のフォームを発射することもできます。
option 、 option-type 、 name 、 expander 、 option 、 remove-option 、 list-options 、 define-option 、 expand-optionsを参照してください
モジュールの概念は、輝きに不可欠です。それは全体の「部分」の表現として機能します。技術レベルでは、モジュールは特別なメタデータが取り付けられたパッケージです。 modularizeシステムによって提供され、フックとトリガー、インターフェイス、および他のいくつかの情報の追跡を容易にするために使用されます。
これがあなたにとって意味することは、標準のdefpackageの代わりに、 define-moduleフォームを使用してプライマリパッケージを定義する必要があることです。構文はdefpackageと同じですが、次のような追加のオプションが含まれています:domainと、このモジュールが動作するプライマリドメインを指定できます(もしあれば)。
モジュールシステムにより、ASDFシステムをモジュールに結び付けることもできます。それが行われた場合、ASDFシステムは「仮想モジュール」になります。これを行うには、システム定義に3つのオプションを追加する必要があります。
:defsystem-depends-on (:radiance)
:class "radiance:virtual-module"
:module-name "MY-MODULE"
これにより、RadianceはASDFシステム情報を識別してモジュールに関連付けることができます。新しいモジュールに必要なシステムとモジュール定義の自動作成については、 create-module参照してください。
virtual-module 、 virtual-module-name 、 define-module 、 define-module-extension 、 delete-module 、 module 、 module-p 、 module-storage module-storage-remove module-identifier module-name 、 current-module 、モジュールドメイン、 module-domain 、 module-permissions 、 module-dependencies 、 module-required-interfaces 、 module-required-systems 、 module-pages 、 module-api-endpoints 、 describe-module 、 find-modules-directory 、 *modules-directory* 、 create-module
ラディアンスがモジュールを互いに統合できるようにするメカニズムの1つはフックです。フックを使用すると、何らかのイベントに応じて任意の関数を実行できます。たとえば、フォーラムソフトウェアは、新しい投稿が作成されるたびにトリガーされるフックをセットアップする場合があります。拡張機能は、追加のタスクを実行するフックのトリガーを定義できます。
フックには任意の数のトリガーが定義されていますが、トリガーをトリガーすることはすべてのトリガーが完了するまで終了しないブロッキング操作であるため、トリガーがそれほど時間がかからないことを確認する必要があります。そのため、長期にわたるトリガー操作により、リクエスト応答が長すぎる可能性があります。
フックはスイッチのように機能し、後で再び「オフ」になるまで、長い間「オン」することができます。その間に新しいトリガーが定義されている場合、それらは自動的に呼び出される必要があります。これはdefine-hook-switchが促進するものです。 2つのフックを生成します。最初のものがトリガーされると、後で定義されるトリガーは、2番目のフックがトリガーされるまで自動的に呼び出されます。これにより、サーバーが既に開始された後にのみトリガーが定義されている場合でもserver-startのトリガーが適切に機能します。
list-hooks 、 define-hook 、 remove-hook 、 define-trigger 、 remove-trigger 、 trigger 、 define-hook-switch参照してください
モノリシックになることを避け、拡張可能なバックエンドを許可するために、輝きにはインターフェイスシステムが含まれます。最も一般的な意味では、インターフェイスは、一部の関数、マクロ、変数などが機能する方法についての約束を提供しますが、実際には実装していません。インターフェイスが作業を概説するすべてのものを作成する実際の機能は、実装にプッシュされます。これにより、ユーザーは特定のバックエンドに縛られることなく、インターフェイスに対してコーディングし、提供された機能を利用できます。
具体的な例については、データベースのインターフェイスがあるとしましょう。さまざまな種類のデータベースがあるため、これは賢明です。これはすべて、さまざまな相互作用方法を提供しますが、それでもすべてが非常に一般的な操作を提供します。データの保存、データの取得、データの変更です。したがって、これらの一般的な操作を提供するインターフェイスを作成します。その後、特定の種類のデータベースが実際の操作を機能させるための実装次第です。アプリケーションライターとして、データベースインターフェイスを利用して、それを使用して、アプリケーションをさまざまなデータベースで自動的に動作させることができます。
アプリケーションライターに利点を与えることに加えて、インターフェイスが提供するというデカップリングは、特定の要件が既存の実装によって満たされない場合、システム管理者が独自の実装を比較的簡単に記述できることを意味します。インターフェイスの不透明度のおかげで、実装は、LISPプロセスで実行されるものと完全に外部のものへのブリッジを提供できます。これにより、生産システムの管理者が必要なものを正確に選択できるようにするために、多くの選択肢がオープンになります。
実際には、インターフェイスは特別な種類のモジュールであり、したがって特別な種類のパッケージです。定義の一部として、関数、変数などの他のバインディングの一連の定義が含まれています。パッケージであるため、ユーザーとして他のパッケージで他のものを使用するのと同じように、インターフェイスのコンポーネントを使用できます。違いはありません。実装ライターとして、インターフェイスが概説するすべての定義を再定義するだけです。
インターフェイスを使用するモジュールを実際にロードするには、インターフェイスの実装を事前にロードする必要があります。それ以外の場合、マクロは適切に機能しませんでした。したがって、特定の実装を参照することなくASDFシステム定義のインターフェイスに依存することを許可するために、RadianceはASDF拡張を提供します。この拡張機能により(:interface :foo)などのリストを:depends-onに追加できます。その後、Moduleがロードされたときに、Radianceはそのコンクリートの実装にインターフェイスを解決します。
放射輝度は、標準的なインターフェイスの束を提供します。これらの各インターフェイスには、放射輝度が提供する少なくとも1つの標準的な実装があります。インターフェイスは次のとおりです。
adminauthbancachedatabaseloggermailprofilerateserversessionuserインターフェイスについては、以下で詳しく説明します。
interface 、 interface-p 、 implementation 、 implements 、 reset-interface 、 define-interface-extension 、 find-implementation 、 load-implementation 、 define-interface 、 define-implement-triggerを参照してください
同じマシンでさまざまなセットアップを使用した輝きの複数のインスタンスを実行することを許可するために、Radianceは環境システムと呼ばれるものを提供します。環境は、基本的に、Radiance自体とすべてのロードされたモジュールの構成ファイルとランタイムファイルのセットです。ラディアンス構成には、選択した実装へのインターフェイスのマッピングも含まれているため、インターフェイスが要求された場合に何を選択するかを決定します。
使用される特定の環境は、 startupが呼び出されたときに最新の環境で選択され、モジュールがロードされたときに最古の環境が選択されます。後者の場合、環境を選択できるように、インタラクティブな再起動が提供されます。それ以外の場合は、輝きがインターフェイスマッピングを解決できないため、これが必要です。
環境システムの一部として、Radianceは、アプリケーションに使用できる - そしておそらくすべきである可能性がある構成システムを提供します。各環境で設定が適切に多重化され、設定が常に永続的であることが保証されます。また、特別なツールを必要とせずにファイルを読み取り、変更できるように、人間の読み取り可能なストレージ形式を使用します。
構成ストレージの実際の取り扱いと使用率については、ユビキタスを参照してください。 value関数の代わりに、Radianceがconfig関数を提供することに注意してください。
構成ファイルとは別に、環境は、ユーザーのアップロード、キャッシュファイルなど、ランタイムデータファイルの一貫したストレージロケーションも提供します。 environment-module-directoryとenvironment-module-pathnameを使用して、この場所を取得できます。アップロードとキャッシュを保存する場合、モジュールはこれらのパスを使用して、管理者に一貫したインターフェイスを提示する必要があります。
展開されたシステムでは、環境ストレージパスの位置を変更することが望まれる場合があります。その場合、管理者は、 environment-directoryおよびenvironment-module-directoryに関する新しい方法を提供して、必要に応じて動作をカスタマイズすることが奨励されます。詳細とデフォルトのアクションについては、関連するドキュメント文字列も参照してください。
環境により、管理者のオーバーライドも可能になります。以下を使用すると、 environment-module-directory用の:staticおよび:templateタイプにより、モジュールの標準テンプレートと静的ファイルをオーバーライドするファイルを保存するパスが得られます。それぞれのディレクトリ内のパスは、モジュール独自のソースファイルのパスと一致する必要があります。モジュールが実際に使用する静的ファイルとテンプレートファイルは、モジュールのロードタイムでキャッシュされているため、LISP画像が再起動されたり、モジュールのソースファイルがリロードされない限り変更されないことに注意してください。
environment-change 、 environment 、 environment-directory 、 environment-module-directory 、 environment-module-pathname 、 check-environment 、マコンフィグmconfig-pathname mconfig-storage 、 mconfig 、 defaulted-mconfig 、 config 、 defaulted-config 、 template-file 、 @template static-file 、 @static
時には、システムが逆に互換性のない方法で進化することがあります。その場合、既存のセットアップが新しいバージョンで機能し続けるには、ランタイムデータの移行が必要です。 Radianceは、このプロセスを自動化し、スムーズなアップグレードを可能にするシステムを提供します。
バージョン間の移行は、Radianceのスタートアップシーケンス中に自動的に発生する必要があります。管理者または著者として、移行が発生するための追加の手順を実行する必要はありません。ただし、モジュール著者として、モジュールに必要なデータ移行手順を実行するためにコードを自然に提供する必要があります。
モジュールを移行可能にするには、バージョン仕様を持つASDFシステムでロードする必要があります。バージョンは、標準の点線数スキームに従い、最後に追加できるオプションのバージョンハッシュを使用する必要があります。次に、 define-version-migrationを使用して、個々のバージョン間の移行ステップを定義できます。定義されると、Radianceはコンクリートバージョンで自動的にピックアップし、現在のターゲットバージョンに到達するために必要な移行を順番に実行します。正確な手順とあなたができることの詳細については、 migrateとmigrate-versions参照してください。
last-known-system-version 、 migrate-versions 、 define-version-migration 、 ready-dependency-for-migration 、 ensure-dependencies-ready 、 versions 、 migrate参照してください
最後に、Radianceは、物事が適切にセットアップされ、準備が整っていることを保証する標準的なスタートアップとシャットダウンシーケンスを提供し、その後再びきれいにクリーンアップします。そのシーケンスの大部分は、特定のフックが適切な順序で適切な時期に呼び出されることを保証することです。
適切なインターフェイス関数を使用してサーバーを手動で開始できますが、そのようにすると、アプリケーションが適切に実行されることを期待しないでください。それらの多くは、適切に動作するために特定のフックが呼び出されることを期待するでしょう。これが、あなたが何をしているのかを正確に知らない限り、常に必要な理由です。 startupとshutdownを使用して、Radianceインスタンスを管理します。 2つの関数のドキュメントは、どのフックがトリガーされ、どの順序でどのフックがトリガーされるかを正確に説明する必要があります。実装は、前述のシンボルがエクスポートされない限り、インターフェイスパッケージのシンボルに関する追加の不特定の定義を提供する場合があります。
*startup-time* 、 uptime 、 server-start 、 server-ready 、 server-stop 、 server-shutdown 、 startup 、 startup-done 、 shutdown 、 shutdown-done 、 started-p参照してください
これらのインターフェイスは輝きで配布されており、コアパッケージの一部です。ただし、ライブラリは追加のインターフェイスを提供する場合があります。標準インターフェイスの実装では、次のインターフェイス定義制約の緩和が許可されています。
実装に依存するキーワード引数によって、さらに&key引数を含むラムダリストをさらに拡張できます。 &optionalが含まれているが、 &keyまたは&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &restのリスト。必要な引数のみを含むLambdaリストは、さらにオプションまたはキーワードの引数によって拡張される場合があります。
このインターフェイスは、管理ページを提供します。あらゆる種類のユーザー構成可能な設定、またはシステム情報表示に使用する必要があります。 「管理」と呼ばれているにもかかわらず、これはシステムの管理者のみを対象としたものではないことに注意してください。ページは、任意のユーザーに使用可能である必要があります。
管理ページは、分類されたメニューとパネルを表示できるようにする必要があります。パネルは他のモジュールによって提供され、 admin:define-panelを介して追加できます。機密操作へのアクセスを提供するパネルは、 :accessオプションと非デフォルト許可を通じて適切に制限される必要があります。許可に関する説明については、ユーザーインターフェイスを参照してください。
管理ページまたはその上の特定のパネルにリンクするには、 pageリソースタイプを使用します。
admin:list-panels 、 admin:remove-panel 、 admin:define-panel 、 admin:panelを参照してください
認証インターフェイスは、ユーザーをリクエストに結び付ける責任があります。このため、ユーザーがシステムに対して自分自身を認証できる方法を提供する必要があります。これが正確に行われる方法は、実装次第です。ただし、実装は、認証プロセスが開始されるページを提供する必要があります。 You can get a URI to it through the page resource and passing "login" as argument.
You can test for the user currently tied to the request by auth:current . This may also return NIL , in which case the user should be interpreted as being "anonymous" . See the user interface for more information.
See auth:*login-timeout* , auth:page , auth:current , auth:associate
This interface provides for IP-banning. It must prevent any client connecting through a banned IP from seeing the content of the actual page they're requesting. Bans can be lifted manually or automatically after a timeout. The implementation may or may not exert additional effort to track users across IPs.
See ban:jail , ban:list , ban:jail-time , ban:release
The cache interface provides for a generic caching mechanism with a customisable invalidation test. You can explicitly renew the cache by cache:renew . To define a cached block, simply use cache:with-cache , which will cause the cached value of the body to be returned if the test form evaluates to true.
The exact manner by which the cached value is stored is up to the implementation and cache:get or cache:with-cache may coerce the cached value to a string or byte array. The implementation may support any number of types of values to cache, but must in the very least support strings and byte arrays.
The name for a cached value must be a symbol whose name and package name do not contain any of the following characters: <>:"/|?*. The variant for a cached value must be an object that can be discriminated by its printed (as by princ ) representation. The same character constraints as for the name apply.
See cache:get , cache:renew , cache:with-cache
This interface provides you with a data persistence layer, usually called a database. This does not have to be a relational database, but may be one. In order to preserve implementation variance, only basic database operations are supported (no joins, triggers, etc). Data types are also restricted to integers, floats, and strings. Despite these constraints, the database interface is sufficiently useful for most applications.
Note that particular terminology is used to distance from traditional RDBMS terms: a schema is called a "structure". A table is called a "collection". A row is called a "record".
Performing database operations before the database is connected results in undefined behaviour. Thus, you should put your collection creation forms ( db:create ) within a trigger on db:connected . Radiance ensures that the database is connected while Radiance is running, so using the database interface in any page, api, or uri dispatcher definitions is completely fine.
The functions for actually performing data storage are, intuitively enough, called db:insert , db:remove , db:update , db:select , and db:iterate . The behaviour thereof should be pretty much what you'd expect. See the respective docstrings for a close inspection. Also see the docstring of db:create for a lengthy explanation on how to create a collection and what kind of restrictions are imposed.
The database must ensure that once a data manipulation operation has completed, the changes caused by it will be persisted across a restart of Radiance, the lisp image, or the machine, even in the case of an unforeseen crash.
See database:condition , database:connection-failed , database:connection-already-open , database:collection-condition , database:invalid-collection , database:collection-already-exists , database:invalid-field , database:id , database:ensure-id , database:connect , database:disconnect , database:connected-p , database:collections , database:collection-exists-p , database:create , database:structure , database:empty , database:drop , database:iterate , database:select , database:count , database:insert , database:remove , database:update , database:with-transaction , database:query , database:connected , database:disconnected
This interface provides primitive logging functions so that you can log messages about relevant happenings in the system. The actual configuration of what gets logged where and how is up to the implementation and the administrator of the system.
See logger:log , logger:trace , logger:debug , logger:info , logger:warn , logger:error , logger:severe , logger:fatal
With the mail interface you get a very minimal facility to send emails. A variety of components might need email access, in order to reach users outside of the website itself. The configuration of the way the emails are sent --remote server, local sendmail, etc.-- is implementation dependant.
The mail:send hook provided by the interface allows you to react to outgoing emails before they are sent.
See mail:send
The profile interface provides extensions to the user interface that are commonly used in applications that want users to have some kind of presence. As part of this, the interface must provide for a page on which a user's "profile" can be displayed. The profile must show panels of some kind. The panels are provided by other modules and can be added by profile:define-panel .
You can get a URI pointing to the profile page of a user through the page resource type.
The interface also provides access to an "avatar image" to visually identify the user ( profile:avatar ), a customisable name that the user can change ( profile:name ), and field types to what kind of data is contained in a user's field and whether it should be public information or not ( profile:fields profile:add-field profile:remove-field ).
See profile:page , profile:avatar , profile:name , profile:fields , profile:add-field , profile:remove-field , profile:list-panels , profile:remove-panel , profile:define-panel , profile:panel
This interface provides for a rate limitation mechanism to prevent spamming or overly eager access to potentially sensitive or costly resources. This happens in two steps. First, the behaviour of the rate limitation is defined for a particular resource by rate:define-limit . Then the resource is protected through the rate:with-limitation macro. If the access to the block by a certain user is too frequent, the block is not called, and the code in the limit definition is evaluated instead.
Note that rate limitation is per-client, -user, or -session depending on the implementation, but certainly not global.
See rate:define-limit , rate:left , rate:with-limitation
This and the logger interface are the only interfaces Radiance requires an implementation for in order to start. It is responsible for accepting and replying to HTTP requests in some manner. The implementation must accept requests and relay them to the Radiance request function, and then relay the returned response back to the requester.
Note that the actual arguments that specify the listener behaviour are implementation-dependant, as is configuration thereof. However, if applicable, the implementation must provide for a standard listener that is accessible on localhost on the port configured in (mconfig :radiance :port) and is started when radiance:startup is called.
See server:start , server:stop , server:listeners , server:started , server:stopped
The session interface provides for tracking a client over the course of multiple requests. It however cannot guarantee to track clients perfectly, as they may do several things in order to cloak or mask themselves or falsify information. Still, for most users, the session tracking should work fine enough.
The session interface is usually used by other interfaces or lower-lying libraries in order to provide persistence of information such as user authentication.
See session:*default-timeout* , session:session , session:= , session:start , session:get , session:list , session:id , session:field , session:timeout , session:end , session:active-p , session:create
This interface provides for persistent user objects and a permissions system. It does not take care of authentication, identification, tracking, or anything of the sort. It merely provides a user object upon which to build and with which permissions can be managed.
See user:user for a description of permissions and their behaviour.
See user:condition , user:not-found , user:user , user:= , user:list , user:get , user:id , user:username , user:fields , user:field , user:remove-field , user:remove , user:check , user:grant , user:revoke , user:add-default-permissions , user:create , user:remove , user:action , user:ready , user:unready
This is an extension of the database interface. Any module implementing this interface must also implement the database interface. This interface provides some extensions to allow more expressive database operations that are only directly supported by relational database systems.
See relational-database:join , relational-database:sql
*environment-root* has been removed as per issue #28 and fix #29. It has instead been replaced by a more generic mechanism for environment directories, incorporated by the function environment-directory . If you previously customised *environment-root* , please now change environment-directory instead, as described in §1.11.template-file and static-file .user:id identifier for each user object, allowing you to reference users in databases and records more efficiently.:unique on db:select and db:iterate . If you'd like to support the continued development of Radiance, please consider becoming a backer on Patreon: