Radiance เป็นสภาพแวดล้อมของเว็บแอปพลิเคชันซึ่งเป็นเหมือนเฟรมเวิร์กเว็บ แต่ทั่วไปมีความยืดหยุ่นมากกว่า ควรให้คุณเขียนเว็บไซต์ส่วนบุคคลและแอปพลิเคชันที่ปรับใช้งานได้โดยทั่วไปได้อย่างง่ายดายและในลักษณะที่พวกเขาสามารถใช้ในการตั้งค่าใด ๆ โดยไม่ต้องผ่านการดัดแปลงพิเศษ
โมดูลและแอพพลิเคชั่นที่เกี่ยวข้องและแอปพลิเคชันที่เกี่ยวข้องจะถูกแจกจ่ายผ่าน Quicklisp ใน DIST แยกต่างหาก ในการติดตั้ง Radiance ทำ:
(ql-dist:install-dist "http://dist.shirakumo.org/shirakumo.txt")
(ql:quickload :radiance)
จากที่นั่นคุณควรจะสามารถโหลดและใช้โมดูล Radiance ทุกชนิดเช่นสีม่วงโดยตรงผ่าน Quicklisp's quickload
คุณสามารถค้นหาบทช่วยสอนที่แนะนำ Radiance และแนวคิดที่สำคัญส่วนใหญ่และสำรวจวิธีการเขียนเว็บแอปพลิเคชันโดยทั่วไปที่นี่ ควรให้ความรู้สึกที่ดีแก่คุณเกี่ยวกับวิธีการไปเกี่ยวกับสิ่งต่าง ๆ และให้คำแนะนำแก่คุณเกี่ยวกับสถานที่ที่จะดูว่าคุณต้องการคุณสมบัติเฉพาะหรือไม่ ในส่วนสุดท้ายมันจะเข้าสู่การตั้งค่าจริงและการปรับใช้การติดตั้ง Radiance บนเซิร์ฟเวอร์การผลิต
สิ่งพื้นฐานที่สุดที่คุณต้องการทำคือให้บริการ HTML บางชนิด ลองทำงานต่อไปและค่อยๆขยายออกไป ก่อนที่เราจะเริ่มต้นได้เราต้องเริ่มต้นความกระจ่างใส
( ql :quickload :radiance )
( radiance :startup) หากนี่เป็นครั้งแรกที่คุณตั้งค่าความกระจ่างใสคุณจะได้รับบันทึกเกี่ยวกับมันโดยใช้โมดูล r-welcome นอกจากนี้ยังควรให้ลิงค์ที่คุณสามารถเปิดในเบราว์เซอร์ของคุณเพื่อดูหน้าทักทายเล็กน้อย สำหรับตอนนี้เราแค่ต้องการวางหน้าเล็ก ๆ ของเราเองข้างๆ
( in-package :rad-user )
(define-page example " /example " ()
( setf (content-type *response* ) " text/plain " )
" Hi! " )การเยี่ยมชม LocalHost: 8080/ตัวอย่างตอนนี้ควรแสดง "สวัสดี" ค่อนข้างน่าเบื่อแน่นอน ลองคาย HTML ออกมาแทน สำหรับตอนนี้เราจะใช้ Cl-Who เพราะมันง่ายมาก ขั้นแรกให้ quickload จากนั้นเรียกใช้สิ่งต่อไปนี้:
(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 หลักและสองโฟลเดอร์ 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 ง่าย ๆ เพื่อทำให้สิ่งต่าง ๆ เพิ่มขึ้นเล็กน้อย ไฟล์จะเป็น example.css ที่วางไว้ในโฟลเดอร์ static นี่คือตัวอย่าง 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 ของเราเพื่อเชื่อมโยงไปยังแผ่นสไตล์จริง เพื่อให้ที่อยู่ไปยังสไตล์ชีทเราจะต้องใช้ประโยชน์จากระบบการกำหนดเส้นทางของ 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. " ))))))) รีเฟรชหน้าและvoilàตอนนี้มันมีพิซซ่าบางอย่างด้วย คุณอาจต้องการคำอธิบายสำหรับธุรกิจ uri-to-url ทั้งหมด การอธิบายอย่างเต็มรูปแบบนั้นได้รับการจัดการโดยส่วนที่ติดตามส่วนนี้ แต่ส่วนสำคัญของมันก็คือมันทำให้มั่นใจได้ว่าลิงก์ไปยังไฟล์คงที่ได้รับการแก้ไขอย่างเหมาะสมภายใต้การตั้งค่าใด ๆ
หนึ่งในแนวคิดที่สำคัญที่สุดในการเปล่งประกายคือ URI URI เป็นวัตถุที่ประกอบด้วยรายการของโดเมนหมายเลขพอร์ตเสริมและเส้นทาง (ดู uri ) โดยพื้นฐานแล้วมันเป็นรุ่น URI ทั่วไปที่ถูกถอดออกและไม่รวมถึงสคีมา, แบบสอบถามหรือส่วนของชิ้นส่วน ความแตกต่างที่สำคัญอีกประการหนึ่งคือ domains URIs ถูกนำมาใช้ในหลาย ๆ จุดตลอดกรอบการทำงานทั้งเพื่อจับตำแหน่งและเพื่อจัดการการจับคู่การจัดส่ง
โปรดทราบว่า URIS ไม่แน่นอน นี่เป็นสิ่งสำคัญสำหรับประสิทธิภาพเนื่องจากการปรับเปลี่ยน URI จะต้องเกิดขึ้นในหลายส่วนที่อยู่บนเส้นทางวิกฤต อย่างไรก็ตามในกรณีปกติไม่คาดว่า URIs จะได้รับการแก้ไขนอกฟังก์ชั่นที่เลือกสองสามฟังก์ชั่น การปรับเปลี่ยนชิ้นส่วนของ 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 , copy-uri , parse-uri , uri< , uri> , uri= , uri-matches , merge-uris , represent-uri , uri-to-url
เพื่อที่จะห่อหุ้มข้อมูลที่ส่งไปและกลับจากเรามีความคิดในการร้องขอ ( request ) และการตอบสนอง ( response ) วัตถุคำขอถือ URI ที่แสดงถึงตำแหน่งใดที่คำขอไปและข้อมูลทั้งหมดที่มีอยู่ใน HTTP Payload เช่นโพสต์, GET, ส่วนหัวและตัวแปรคุกกี้ วัตถุตอบสนองเก็บรหัสกลับส่วนหัวคุกกี้และข้อมูลร่างกายจริง
ในระหว่างการประมวลผลของคำขอวัตถุทั้งสองนี้จะต้องมีอยู่และผูกพันกับตัวแปร *response* และ *request* * * * * * * * * พวกเขาห่อหุ้มข้อมูลที่สำคัญมากที่จำเป็นในการสร้างหน้าแบบไดนามิก นอกจากนี้คำขอยังมีตาราง data ทึบแสงที่คุณสามารถจัดเก็บข้อมูลโดยพลการ สิ่งนี้มีประโยชน์เมื่อคุณต้องการแลกเปลี่ยนข้อมูลระหว่างแต่ละส่วนของระบบที่อาจส่งถึงในระหว่างการดำเนินการตามคำขอ
คำขอไม่จำเป็นต้องมาจากเซิร์ฟเวอร์ HTTP ในการทดสอบสิ่งต่าง ๆ คุณสามารถสร้างคำขอด้วยตัวเองและส่งออกเป็นโปรแกรม ไม่ว่ากรณีใดอินเทอร์เฟซหลักในการส่งคำขอเรียกว่า request สิ่งนี้จะสร้างวัตถุคำขอและการตอบสนองสำหรับคุณและจัดการ URI อย่างเหมาะสม หากคุณต้องการทำสิ่งนั้นด้วยตัวเองและ เพียง แค่ส่งวัตถุคำขอที่สมบูรณ์คุณสามารถใช้ execute-request
สำหรับการจัดการที่แท้จริงของคำขอให้ดู dispatchers หน้าและจุดสิ้นสุด API
ดู *request* , *response* , *default-external-format* , *default-content-type* , request , uri , http-method , body-stream cookie headers headers , name return-code post-data data get-data , cookies , user-agent referer external-format response , domain cookies data issue-time remote value content-type domain , path , expires , http-only , secure , cookie-header , cookie , get-var , post-var ร์, post/get , header , file request redirect handle-condition serve-file render-error-page execute-request request-run-time , *debugger* set-data
ก่อนที่จะมีการร้องขอสามารถส่งผ่านสิ่งที่เรียกว่าระบบการกำหนดเส้นทาง ซึ่งแตกต่างจากเฟรมเวิร์กอื่น ๆ ที่ 'เส้นทาง' กำหนดสิ่งที่จัดการกับคำขอใน Radiance A เส้นทาง ( route ) เป็นรูปแบบของนักแปล URI ส่วนหนึ่งของระบบนี้เป็นสิ่งที่รับผิดชอบในการสร้างและสนับสนุน "จักรวาล" สองแห่งซึ่งเป็นสิ่งภายในและภายนอก
จักรวาลภายในเป็นเว็บแอปพลิเคชันจริงหนึ่งที่อาศัยอยู่ในจักรวาลภายนอกเป็นหนึ่งในเซิร์ฟเวอร์ HTTP และผู้ใช้เว็บไซต์อาศัยอยู่ความแตกต่างนี้เป็นสิ่งจำเป็นเพื่อให้คุณได้หนึ่งมือเดียวเขียนเว็บแอปพลิเคชันโดยไม่ต้องกังวลเกี่ยวกับการตั้งค่าที่อาจเกิดขึ้นบนเซิร์ฟเวอร์ คุณไม่ต้องกังวลเกี่ยวกับประเภทของโดเมนพอร์ตการตั้งค่าเส้นทางอาจจำเป็นในการเรียกใช้แอปพลิเคชันของคุณ ในทางกลับกันจะช่วยให้คุณเป็น webadmin ในการปรับแต่งและเรียกใช้ระบบตามความต้องการที่แน่นอนของคุณโดยไม่ต้องกลัวว่าจะทำลายสิ่งต่างๆ
ทั้งหมดนี้ได้รับการอำนวยความสะดวกโดยเส้นทางซึ่งมีสองชนิดคือการทำแผนที่และเส้นทางการพลิกกลับ เส้นทางการทำแผนที่มีหน้าที่ในการเปลี่ยน URI จากจักรวาลภายนอกเป็นหนึ่งในจักรวาลภายใน โดยปกติแล้วสิ่งนี้เกี่ยวข้องกับการตัดโดเมนระดับบนสุดและอาจทำแผนที่ของโดเมนย่อย เส้นทางการพลิกกลับทำสิ่งที่ตรงกันข้าม- พวกเขาไปจากจักรวาลภายในไปยังภายนอก สิ่งนี้จำเป็นเพื่อสร้างลิงก์ในหน้าเสิร์ฟของคุณอ้างถึงทรัพยากรที่สามารถเข้าถึงได้จริงจากภายนอก โดยปกติแล้วสิ่งนี้เกี่ยวข้องกับการย้อนกลับการทำแผนที่โดเมนย่อยและเพิ่มโดเมนระดับบนสุดอีกครั้ง
เส้นทางสามารถทำงานโดยพลการ ในระดับพื้นฐานที่สุดพวกเขาเป็นเพียงฟังก์ชั่นที่ปรับเปลี่ยน URI ในบางแฟชั่น สิ่งนี้ช่วยให้คุณสร้างระบบที่ยืดหยุ่นได้ซึ่งควรมีประสิทธิภาพเพียงพอที่จะรองรับความต้องการทั้งหมดของคุณในฐานะผู้ดูแลระบบ ในฐานะนักเขียนแอปพลิเคชันคุณเพียงแค่ต้องตรวจสอบให้แน่ใจว่าใช้ external-uri หรือ uri-to-url บนลิงก์ทั้งหมดที่คุณใส่ลงในหน้าเว็บของคุณ
ดู route , name , direction , priority , translator , route , remove-route list-routes define-route , define-target-route , define-matching-route define-string-route internal-uri external-uri
ในที่สุดเราก็มาถึงส่วนที่สร้างเนื้อหาสำหรับคำขอ URI Dispatchers เป็นคลาสย่อยของ URI ที่มีชื่อฟังก์ชั่นและลำดับความสำคัญ รายการสดในรายการลำดับความสำคัญซึ่งดำเนินการเมื่อใดก็ตามที่มีการร้องขอมาถึง URI ของคำขอถูกจับคู่กับแต่ละ dispatcher ฟังก์ชั่นของ dispatcher แรกที่ตรงกับจะถูกดำเนินการ
และนั่นคือ ฟังก์ชั่นของ dispatcher รับผิดชอบในการตั้งค่าค่าที่จำเป็นในวัตถุตอบสนองเพื่อส่งเนื้อหาหน้า ในการทำเช่นนี้สามารถตั้งค่าฟิลด์ data ของวัตถุตอบกลับโดยตรงหรือคุณสามารถส่งคืนค่าที่เหมาะสมจากฟังก์ชั่น Radiance ยอมรับค่าสี่ประเภทเท่านั้น: stream pathname string และ (array (unsigned-byte 8))
หากตัวแจกจ่าย 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 ซึ่งให้บริการไฟล์ที่เกี่ยวข้องจาก static/ ไดเรกทอรีของ Radiance คุณอาจต้องการให้หน้าของคุณเองสำหรับสิ่งนั้นหรืออัปเดตไฟล์บนเซิร์ฟเวอร์การผลิตของคุณ
จากนั้นมีหน้า static ซึ่งรับผิดชอบในการให้บริการเนื้อหาคงที่สำหรับเว็บแอปพลิเคชันและโมดูลทั้งหมด มันควรจะใช้งานอยู่ในโดเมนใด ๆ และเสมอบนเส้นทาง /static/... ที่ ... จะต้องมีรูปแบบที่ไดเรกทอรีแรกคือชื่อของโมดูลและส่วนที่เหลือเป็นเส้นทางภายใน static/ ไดเรกทอรีของโมดูลนั้น สิ่งนี้ช่วยให้คุณสามารถอ้างถึงไฟล์คงที่เช่น CSS, JS และรูปภาพผ่านเส้นทางทั่วไป
ในที่สุดก็มีหน้า api ซึ่งรับผิดชอบในการจัดการการจัดส่งจุดสิ้นสุด API ซึ่งอธิบายไว้ในส่วนต่อไปนี้ หน้านั้นทำหน้าที่คล้ายกับรูปแบบคงที่โดยการจับ /api/... เส้นทางในทุกโดเมน
ดู page , remove-page , define-page
Radiance ให้การสนับสนุนแบบบูรณาการสำหรับคำจำกัดความ REST API นี่ไม่ได้เป็นเพียงคุณสมบัติที่ถูกยึดติด แต่เป็นเพราะแอพพลิเคชั่นที่ทันสมัยส่วนใหญ่ต้องการให้ API บางชนิดและเนื่องจาก Radiance แนะนำวิธีการเขียนแอปพลิเคชันของคุณซึ่งจำเป็นต้องเกี่ยวข้องกับจุดสิ้นสุดของ API
แนวคิดเกี่ยวกับจุดสิ้นสุด API เป็นฟังก์ชั่นที่เรียกได้ผ่านคำขอเบราว์เซอร์ การตอบสนองของพวกเขาจะถูกทำให้เป็นรูปแบบที่สามารถอ่านได้โดยผู้ร้องขอไม่ว่าจะเป็นอะไรก็ตาม สิ่งสำคัญที่ต้องจำไว้คือจุดสิ้นสุดของ API ควรใช้งานได้ทั้งผู้ใช้และโปรแกรม Radiance สนับสนุนสิ่งนี้เพราะโดยปกติแล้วการกระทำใด ๆ ที่สามารถดำเนินการทางโปรแกรมผ่าน API จะต้องดำเนินการโดยผู้ใช้ในบางวิธี เพื่อหลีกเลี่ยงการทำซ้ำทั้งสองสามารถ conflated
ดังนั้นโดยปกติแล้วการดำเนินการปรับเปลี่ยนข้อมูลทุกประเภทควรได้รับผ่านจุดสิ้นสุด API ที่ตอบสนองแตกต่างกันเล็กน้อยขึ้นอยู่กับว่าผู้ใช้หรือแอปพลิเคชันร้องขอหรือไม่ ในกรณีของผู้ใช้มักจะเปลี่ยนเส้นทางกลับไปยังหน้าเว็บที่เหมาะสมและในกรณีของแอปพลิเคชันควรให้ข้อมูลข้อมูลในรูปแบบที่อ่านได้
ส่วนแรกของทั้งหมดนี้คือระบบรูปแบบ API ซึ่งรับผิดชอบในการจัดลำดับข้อมูลในรูปแบบที่ระบุบางอย่าง โดยค่าเริ่มต้นมีเพียงรูปแบบที่ใช้การแสดงออกของ S แต่สามารถโหลดเอาต์พุต JSON ได้อย่างง่ายดาย
ส่วนที่สองคือข้อกำหนดของพารามิเตอร์โพสต์/รับเบ browser ว์เซอร์ หากพารามิเตอร์นั้นมีสตริงที่แน่นอน "true" คำขอ API จะได้รับการปฏิบัติที่มาจากผู้ใช้และทำให้การเปลี่ยนเส้นทางแทนที่จะส่งข้อมูลควรส่งออก
แอปพลิเคชันของคุณควรใช้ประโยชน์จากสิ่งเหล่านั้นเพื่อให้ API แบบบูรณาการอย่างเหมาะสม ตอนนี้คำจำกัดความปลายทางที่แท้จริงประกอบด้วยชื่อฟังก์ชันดิบรายการแลมบ์ดาที่อธิบายถึงอาร์กิวเมนต์ของฟังก์ชั่นและฟังก์ชั่นการแยกวิเคราะห์คำขอ โดยทั่วไปแล้วสำหรับข้อโต้แย้งของคุณมีเพียงข้อโต้แย้งที่จำเป็นและเป็นตัวเลือกเท่านั้น ท้ายที่สุดคำขอ HTTP มีเพียง "อาร์กิวเมนต์คำหลัก" ที่สามารถให้ได้และสามารถนำเสนอหรือหายไปได้
ชื่อของจุดสิ้นสุด API ยังทำหน้าที่เป็นตัวระบุที่บอกคุณว่าคุณสามารถเข้าถึงได้ที่ไหน จุดสิ้นสุด API อาศัยอยู่บน /api/ PATH ตามด้วยชื่อของจุดสิ้นสุด ดังนั้นคุณต้องรับผิดชอบในการนำหน้าจุดปลายของคุณด้วยชื่อโมดูลหรือแอปพลิเคชันของคุณเพื่อหลีกเลี่ยงการสะดุดจุดปลายอื่น ๆ โดยไม่ตั้งใจ สิ่งนี้แตกต่างจากใน URI dispatchers เนื่องจากจุดสิ้นสุด API ต้องจับคู่อย่างแน่นอนและไม่อนุญาตให้มีความกำกวมหรือการประมวลผลของเส้นทาง ดังนั้นทุกจุดปลายจะต้องมีเส้นทางที่ไม่ซ้ำกันซึ่งสามารถใช้เป็นชื่อได้ทันที
ฟังก์ชั่นดิบเป็นฟังก์ชั่นที่ API ให้อินเทอร์เฟซสำหรับ มันมีหน้าที่รับผิดชอบในการดำเนินการตามที่ร้องขอและส่งคืนข้อมูลที่เหมาะสมตามที่อธิบายไว้ข้างต้น สำหรับการส่งคืนข้อมูล API ที่จัดรูปแบบให้ดู api-output สำหรับการเปลี่ยนเส้นทางในกรณีของคำขอเบราว์เซอร์ดู redirect
ในที่สุดฟังก์ชั่นการแยกวิเคราะห์คำขอมีหน้าที่รับผิดชอบในการใช้วัตถุคำขอแยกอาร์กิวเมนต์ที่ฟังก์ชั่นต้องการจากมันและในที่สุดก็เรียกฟังก์ชั่นนั้นด้วยอาร์กิวเมนต์ที่เหมาะสม- ถ้าเป็นไปได้ ฟังก์ชั่นการแยกวิเคราะห์อาจส่งสัญญาณข้อผิดพลาด api-argument-missing หากอาร์กิวเมนต์ที่ต้องการหายไป อาร์กิวเมนต์ที่ฟุ่มเฟือยควรถูกละเว้น
นอกจากนี้คุณยังสามารถโทรหาจุดสิ้นสุด API โดยใช้ call-api หรือจำลองการเรียกร้องการร้องขอด้วย call-api-request โดยไม่ต้องผ่านกลไกการส่ง URI ทั้งหมด
ในทำนองเดียวกันกับหน้าคำจำกัดความของจุดสิ้นสุด API ยังยอมรับตัวเลือกที่ขยายได้ซึ่งทำให้คำจำกัดความง่ายขึ้น ดูส่วนต่อไปนี้สำหรับคำอธิบายของตัวเลือก
ดู api , *default-api-format* , *serialize-fallback* , api-format , remove-api-format handler argslist list-api-formats remove-api-endpoint define request-handler list-api-endpoints name define-api-format , api-endpoint api-output , call-api-request api-serialize call-api api-endpoint define-api
ตัวเลือกเป็นวิธีการให้มาโครคำจำกัดความที่ขยายได้ สิ่งนี้มีประโยชน์เมื่อเฟรมเวิร์กให้วิธีการทั่วไปในการกำหนดบางสิ่ง แต่ส่วนอื่น ๆ อาจต้องการให้ส่วนขยายไปยังที่เพื่อให้การดำเนินงานทั่วไปสั้นลง ตัวอย่างเช่นงานทั่วไปคือการ จำกัด จุดสิ้นสุดของหน้าหรือ API ให้กับผู้ที่มีข้อมูลรับรองการเข้าถึงที่จำเป็น
เพื่ออำนวยความสะดวกในเรื่องนี้ Radiance ให้กลไกทางเลือกทั่วไป ตัวเลือกจะถูกแบ่งออกเป็นประเภทตัวเลือกที่กำหนดให้มาโครนิยามตัวเลือกที่เป็นของตัวเลือก Radiance จัดเตรียมประเภทตัวเลือก api และ page นอกกล่อง
แต่ละตัวเลือกมีคำหลักสำหรับชื่อและฟังก์ชั่น expander ที่ต้องยอมรับอาร์กิวเมนต์จำนวนหนึ่งขึ้นอยู่กับประเภทตัวเลือก ให้เป็นข้อโต้แย้งเสมอคือชื่อของสิ่งที่กำหนดไว้รายการของรูปแบบร่างกายของคำจำกัดความและค่าสุดท้ายเป็นทางเลือกที่มีให้กับตัวเลือกในรายการตัวเลือกหากมีการกล่าวถึงเลย ฟังก์ชั่นการขยายตัวนี้จะรับผิดชอบในการเปลี่ยนรูปแบบร่างกายของมาโครนิยามในบางวิธี นอกจากนี้ยังสามารถปล่อยรูปแบบที่สองที่วางอยู่นอกคำจำกัดความของตัวเองเพื่ออนุญาตให้ตั้งค่าสภาพแวดล้อมในบางลักษณะ
ดู option , option-type , name , expander , option , remove-option ตัวเลือก, list-options , define-option , expand-options
แนวคิดของโมดูลมีความสำคัญต่อความกระจ่างใส มันทำหน้าที่เป็นตัวแทนของ "ส่วน" ของทั้งหมด ในระดับเทคนิคโมดูลเป็นแพ็คเกจที่มีข้อมูลเมตาพิเศษที่แนบมากับมัน มันจัดทำโดยระบบ modularize และใช้เพื่ออำนวยความสะดวกให้ตะขอและทริกเกอร์อินเทอร์เฟซและการติดตามข้อมูลอื่น ๆ สองสามชิ้น
สิ่งนี้มีความหมายสำหรับคุณคือแทนที่จะเป็น defpackage มาตรฐานคุณควรใช้แบบฟอร์ม define-module เพื่อกำหนดแพ็คเกจหลักของคุณ ไวยากรณ์เหมือนกับ defpackage แต่มีตัวเลือกพิเศษบางอย่างเช่น :domain ซึ่งช่วยให้คุณสามารถระบุโดเมนหลักที่โมดูลนี้ควรทำงาน (ถ้ามี)
ระบบโมดูลยังช่วยให้ระบบ ASDF ผูกโมดูล หากทำเช่นนั้นระบบ ASDF จะกลายเป็น "โมดูลเสมือน" ในการทำเช่นนี้คุณต้องเพิ่มสามตัวเลือกลงในนิยามระบบของคุณ:
:defsystem-depends-on (:radiance)
:class "radiance:virtual-module"
:module-name "MY-MODULE"
สิ่งนี้ช่วยให้ Radiance ระบุและเชื่อมโยงข้อมูลระบบ ASDF เข้ากับโมดูลของคุณ สำหรับการสร้างคำจำกัดความของระบบและโมดูลที่จำเป็นโดยอัตโนมัติสำหรับโมดูลใหม่ให้ดู create-module
ดู virtual-module define-module virtual-module-name , define define-module-extension module delete-module module-p module-storage , โมดูล-โมดูล current-module - module-domain module-permissions module-storage-remove module-dependencies module-identifier module-required-interfaces module-name module-required-systems , module-pages , module-api-endpoints , describe-module , find-modules-directory , *modules-directory* , create-module
หนึ่งในกลไกที่ Radiance ให้เพื่ออนุญาตให้รวมโมดูลเข้าด้วยกันคือตะขอ Hooks ช่วยให้คุณใช้ฟังก์ชั่นโดยพลการเพื่อตอบสนองต่อเหตุการณ์บางประเภท ตัวอย่างเช่นซอฟต์แวร์ฟอรัมอาจตั้งค่าตะขอที่ถูกเรียกใช้เมื่อใดก็ตามที่มีการสร้างโพสต์ใหม่ ส่วนขยายสามารถกำหนดทริกเกอร์บนตะขอนั้นที่ทำงานเพิ่มเติม
ตะขอสามารถมีจำนวนทริกเกอร์ที่กำหนดไว้โดยพลการ แต่คุณควรตรวจสอบให้แน่ใจว่าทริกเกอร์ใช้เวลาไม่นานเกินไปเนื่องจากการกระตุ้นการทำงานของตะขอคือการปิดกั้นที่จะไม่เสร็จสิ้นจนกว่าทริกเกอร์ทั้งหมดจะเสร็จสิ้น ดังนั้นการดำเนินการทริกเกอร์ที่ดำเนินมายาวนานอาจชะลอการตอบสนองการร้องขอเป็นเวลานานเกินไป
บางครั้งตะขอควรทำหน้าที่เหมือนสวิตช์มากขึ้นซึ่งพวกเขาสามารถ "เปิด" เป็นเวลานานจนกว่าพวกเขาจะปิด "ปิด" อีกครั้งในภายหลัง หากทริกเกอร์ใหม่ถูกกำหนดในช่วงเวลานั้นพวกเขาควรจะถูกเรียกโดยอัตโนมัติ นี่คือสิ่งที่ define-hook-switch อำนวยความสะดวก มันผลิตตะขอสองใบ เมื่อมีการทริกเกอร์ครั้งแรกทริกเกอร์ใด ๆ ที่กำหนดไว้ในภายหลังเรียกว่าโดยอัตโนมัติจนกว่าจะมีการทริกเกอร์ตะขอที่สอง สิ่งนี้จะช่วยให้ทริกเกอร์บนตะขอเช่น server-start ทำงานได้อย่างถูกต้องแม้ว่าทริกเกอร์จะถูกกำหนดไว้หลังจากเซิร์ฟเวอร์เริ่มต้นแล้ว
ดู list-hooks , define-hook , remove-hook , define-trigger , remove-trigger , trigger , define-hook-switch
เพื่อหลีกเลี่ยงการกลายเป็นเสาหินและเพื่อให้แบ็คเอนด์ที่ขยายได้ความเปล่งปลั่งรวมถึงระบบอินเทอร์เฟซ โดยทั่วไปแล้วอินเทอร์เฟซให้คำมั่นสัญญาว่าฟังก์ชั่นบางอย่างมาโครตัวแปร ฯลฯ ควรทำงานอย่างไร แต่ไม่ได้ใช้งานจริง ฟังก์ชั่นจริงที่ทำให้ทุกอย่างที่อินเทอร์เฟซสรุปผลงานจะถูกผลักออกไปสู่การใช้งาน สิ่งนี้ช่วยให้ผู้ใช้สามารถเขียนโค้ดกับอินเทอร์เฟซและใช้ประโยชน์จากฟังก์ชั่นที่ให้ไว้โดยไม่ผูกมัดตัวเองกับแบ็กเอนด์ใด ๆ
สำหรับตัวอย่างที่เป็นรูปธรรมสมมติว่ามีอินเทอร์เฟซสำหรับฐานข้อมูล สิ่งนี้มีความสมเหตุสมผลเนื่องจากมีฐานข้อมูลหลายประเภทที่มีวิธีการโต้ตอบที่แตกต่างกันมากมาย แต่ก็ยังมีการดำเนินการที่พบบ่อยมากเช่นการจัดเก็บข้อมูลการดึงข้อมูลและการแก้ไขข้อมูล ดังนั้นเราจึงสร้างอินเทอร์เฟซที่เสนอการดำเนินการทั่วไปเหล่านี้ จากนั้นก็ขึ้นอยู่กับการใช้งานฐานข้อมูลประเภทเฉพาะเพื่อให้การดำเนินงานจริงทำงานได้ ในฐานะนักเขียนแอปพลิเคชันคุณสามารถใช้ประโยชน์จากอินเทอร์เฟซฐานข้อมูลและทำให้แอปพลิเคชันของคุณทำงานโดยอัตโนมัติกับฐานข้อมูลที่แตกต่างกันมากมาย
นอกเหนือจากการให้ความได้เปรียบแก่นักเขียนแอปพลิเคชันแล้วการแยกส่วนที่อินเตอร์เฟสให้ยังหมายความว่าผู้ดูแลระบบสามารถเขียนการใช้งานของตนเองได้อย่างง่ายดายหากข้อกำหนดเฉพาะของพวกเขาไม่ได้รับการปฏิบัติตามการใช้งานที่มีอยู่ ต้องขอบคุณความทึบของอินเทอร์เฟซการใช้งานทั้งสองสามารถให้สะพานเชื่อมกับสิ่งที่ทำงานในกระบวนการ LISP และสิ่งที่อยู่ภายนอกอย่างสมบูรณ์ สิ่งนี้ทำให้มีทางเลือกมากมายสำหรับผู้ดูแลระบบระบบการผลิตเพื่อให้พวกเขาเลือกสิ่งที่พวกเขาต้องการ
ในทางปฏิบัติอินเทอร์เฟซเป็นโมดูลชนิดพิเศษและเป็นแพ็คเกจพิเศษ เป็นส่วนหนึ่งของคำจำกัดความของพวกเขาพวกเขารวมชุดของคำจำกัดความสำหรับการผูกอื่น ๆ เช่นฟังก์ชั่นตัวแปร ฯลฯ เนื่องจากเป็นแพ็คเกจในฐานะผู้ใช้คุณสามารถใช้ส่วนประกอบของอินเทอร์เฟซเช่นเดียวกับที่คุณจะใช้สิ่งอื่นใดในแพ็คเกจอื่น ๆ ไม่มีความแตกต่าง ในฐานะนักเขียนการใช้งานคุณเพียงแค่กำหนดคำจำกัดความทั้งหมดที่อินเทอร์เฟซสรุป
เพื่อที่จะโหลดโมดูลที่ใช้ประโยชน์จากอินเทอร์เฟซการใช้งานอินเทอร์เฟซจะต้องโหลดล่วงหน้า มิฉะนั้นมาโครไม่สามารถทำงานได้อย่างถูกต้อง ดังนั้นเพื่อให้อนุญาตขึ้นอยู่กับอินเทอร์เฟซในคำจำกัดความของระบบ ASDF ของคุณโดยไม่ต้องอ้างถึงการใช้งานเฉพาะ Radiance ให้ส่วนขยาย ASDF ส่วนขยายนี้ทำให้สามารถเพิ่มรายการเช่น (:interface :foo) ลงในรายการของคุณ :depends-on รายการ Radiance จะแก้ไขส่วนต่อประสานกับการใช้งานคอนกรีตเมื่อโหลดโมดูล
Radiance ให้อินเทอร์เฟซมาตรฐานจำนวนมาก แต่ละอินเทอร์เฟซเหล่านั้นมีการใช้งานมาตรฐานอย่างน้อยหนึ่งครั้งโดย Radiance-Contribs อินเทอร์เฟซคือ:
adminauthbancachedatabaseloggermailprofilerateserversessionuserอินเทอร์เฟซอธิบายถึงเชิงลึกด้านล่าง
ดู interface , interface-p , implementation , implements , reset-interface , define-interface-extension , find-implementation , load-implementation , การกำหนด define-interface , define-implement-trigger
เพื่อให้อนุญาตให้ใช้งานหลายอินสแตนซ์ของความกระจ่างใสด้วยการตั้งค่าที่แตกต่างกันในเครื่องเดียวกัน Radiance ให้สิ่งที่เรียกว่าระบบสภาพแวดล้อม สภาพแวดล้อมเป็นชุดของการกำหนดค่าและไฟล์รันไทม์สำหรับ Radiance และโมดูลที่โหลดทั้งหมด การกำหนดค่า Radiance ยังรวมถึงการแมปของอินเทอร์เฟซกับการใช้งานที่เลือกและตัดสินใจว่าควรเลือกอะไรหากมีการร้องขออินเทอร์เฟซ
สภาพแวดล้อมเฉพาะที่ใช้ถูกเลือกในช่วงล่าสุดเมื่อเรียกว่า startup และเร็วที่สุดเมื่อโหลดโมดูล ในกรณีหลังมีการรีสตาร์ทแบบโต้ตอบเพื่อให้คุณเลือกสภาพแวดล้อม สิ่งนี้มีความจำเป็นอย่างอื่น Radiance จะไม่สามารถแก้ไขการแมปอินเทอร์เฟซได้
ในฐานะที่เป็นส่วนหนึ่งของระบบสิ่งแวดล้อม Radiance ให้ระบบการกำหนดค่าที่คุณสามารถทำได้-และควรใช้สำหรับแอปพลิเคชันของคุณ ช่วยให้มั่นใจได้ว่าการตั้งค่าจะมีมัลติเพล็กซ์อย่างเหมาะสมสำหรับแต่ละสภาพแวดล้อมและการตั้งค่าจะคงอยู่เสมอ นอกจากนี้ยังใช้รูปแบบการจัดเก็บข้อมูลที่มนุษย์อ่านได้เช่นไฟล์สามารถอ่านและแก้ไขได้โดยไม่ต้องใช้เครื่องมือพิเศษใด ๆ
ดูที่แพร่หลายสำหรับการจัดการจริงและการใช้งานการใช้งานของที่เก็บข้อมูลการกำหนดค่า เพียงโปรดทราบว่าแทนที่จะใช้ฟังก์ชั่น value Radiance ให้ฟังก์ชั่น config
นอกเหนือจากไฟล์การกำหนดค่าสภาพแวดล้อมยังมีตำแหน่งที่เก็บข้อมูลที่สอดคล้องกันสำหรับไฟล์ข้อมูลรันไทม์เช่นการอัปโหลดผู้ใช้ไฟล์แคชและอื่น ๆ คุณสามารถดึงตำแหน่งนี้ได้โดยใช้ environment-module-directory และ environment-module-pathname เมื่อจัดเก็บการอัปโหลดและแคชโมดูลควรใช้ประโยชน์จากเส้นทางเหล่านี้เพื่อนำเสนออินเทอร์เฟซที่สอดคล้องกับผู้ดูแลระบบ
ในระบบที่ปรับใช้อาจต้องการเปลี่ยนตำแหน่งของเส้นทางการจัดเก็บสิ่งแวดล้อมซึ่งในกรณีนี้ผู้ดูแลระบบได้รับการสนับสนุนให้จัดหาวิธีการใหม่เกี่ยวกับ environment-directory สิ่งแวดล้อมและ environment-module-directory เพื่อปรับแต่งพฤติกรรมตามที่ต้องการ ดูเพิ่มเติมที่สตริงเอกสารที่เกี่ยวข้องสำหรับรายละเอียดเพิ่มเติมและการดำเนินการเริ่มต้น
สภาพแวดล้อมยังช่วยให้ผู้ดูแลระบบแทนที่ การใช้ :static และ :template สำหรับ environment-module-directory ช่วยให้คุณสามารถจัดเก็บไฟล์ที่ควรแทนที่เทมเพลตมาตรฐานของโมดูลและไฟล์คงที่ เส้นทางภายในไดเรกทอรีที่เกี่ยวข้องจะต้องตรงกับไฟล์ต้นฉบับของโมดูล โปรดทราบว่าไฟล์แบบคงที่และเทมเพลตที่โมดูลใช้จริงจะใช้ถูกแคชในเวลาโหลดโมดูลและจะไม่เปลี่ยนแปลงเว้นแต่ว่าภาพ LISP จะเริ่มต้นใหม่หรือไฟล์ต้นฉบับของโมดูลจะถูกโหลดซ้ำ
ดู environment-change , environment , environment-directory , environment-module-directory environment-module-pathname -โมดูล-- check-environment , mconfig-pathname , mconfig-storage , mconfig , config defaulted-mconfig @template defaulted-config กำหนด template-file 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 เอกสารของทั้งสองฟังก์ชั่นควรอธิบายอย่างชัดเจนว่าตะขอใดจะถูกทริกเกอร์และลำดับใด การใช้งานอาจให้คำจำกัดความเพิ่มเติมที่ไม่ได้ระบุเกี่ยวกับสัญลักษณ์ในแพ็คเกจอินเตอร์เฟสตราบใดที่สัญลักษณ์ดังกล่าวไม่ได้ส่งออก
ดู *startup-time* , uptime , server-start , server-ready , server-stop , server-shutdown , startup , startup-done , shutdown , shutdown-done , started-p
อินเทอร์เฟซเหล่านี้มีการกระจายด้วย Radiance และเป็นส่วนหนึ่งของแพ็คเกจหลัก อย่างไรก็ตามไลบรารีอาจจัดให้มีอินเทอร์เฟซเพิ่มเติม สำหรับการใช้งานอินเทอร์เฟซมาตรฐานอนุญาตให้มีการผ่อนคลายข้อ จำกัด ของคำจำกัดความอินเตอร์เฟสต่อไปนี้:
รายการแลมบ์ดาที่มีอาร์กิวเมนต์ &key สามารถขยายได้โดยเพิ่มเติมข้อโต้แย้งคำหลักที่ขึ้นกับการนำไปใช้ Lambda-Lists ที่มี &optional แต่ไม่มี &key หรือ &rest อาจขยายออกไปโดยอาร์กิวเมนต์เสริมเพิ่มเติม Lambda-Lists ที่มีอาร์กิวเมนต์ที่จำเป็นเท่านั้นอาจขยายออกไปโดยอาร์กิวเมนต์เพิ่มเติมหรือคำหลักเพิ่มเติม
อินเทอร์เฟซนี้มีไว้สำหรับหน้าการดูแลระบบ ควรใช้สำหรับการตั้งค่าที่ผู้ใช้กำหนดค่าได้หรือการแสดงข้อมูลระบบ โปรดทราบว่าแม้จะถูกเรียกว่า "การดูแลระบบ" แต่ก็ไม่ได้มีไว้สำหรับผู้ดูแลระบบเท่านั้น หน้าควรใช้งานได้สำหรับผู้ใช้ทุกคน
หน้าการดูแลระบบจะต้องสามารถแสดงเมนูที่จัดหมวดหมู่และแผงควบคุม แผงควบคุมนั้นจัดทำโดยโมดูลอื่น ๆ และสามารถเพิ่มผ่าน 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: