第 2 部分 · Web 开发
Web 服务器基础
Web 服务器基础
使用 Racket 的内置 Web 服务器框架构建 HTTP 服务。
启动最简单的服务器
Racket 自带了 web-server 库,无需额外安装:
#lang racket
(require web-server/servlet
web-server/servlet-env)
;; 定义请求处理器
(define (start req)
(response/xexpr
`(html
(head (title "Hello Racket Web"))
(body
(h1 "Hello, Web!")
(p "这是我的第一个 Racket Web 应用。")))))
;; 启动服务器
(serve/servlet start
#:launch-browser? #t
#:port 8080
#:servlet-path "/")
运行这段代码,Racket 会启动一个 Web 服务器并在浏览器中打开 http://localhost:8080。
路由处理
使用 dispatch/servlet 实现 URL 路由:
#lang racket
(require web-server/servlet
web-server/servlet-env
web-server/dispatch)
;; 路由处理器
(define (home-page req)
(response/xexpr
`(html (head (title "首页"))
(body (h1 "欢迎来到首页")))))
(define (about-page req)
(response/xexpr
`(html (head (title "关于"))
(body (h1 "关于我们")))))
(define (user-page req username)
(response/xexpr
`(html (head (title ,(format "用户: ~a" username)))
(body (h1 ,(format "你好, ~a!" username))))))
;; 定义路由
(define-values (dispatch url)
(dispatch-rules
[(("about")) about-page]
[(("user") (string-arg)) user-page]
[else home-page]))
;; 启动
(serve/servlet dispatch
#:port 8080
#:servlet-regexp #rx"")
处理 GET 请求参数
(require web-server/request)
(define (search-page req)
(define binds (request-bindings/raw req))
(define query (bindings-assq #"q" binds))
(response/xexpr
`(html
(head (title "搜索结果"))
(body
(h1 "搜索")
(p ,(if query
(format "你搜索了: ~a" (bytes->string/utf-8 (binding:form-value query)))
"请输入搜索关键词"))))))
处理 POST 请求
(define (handle-form req)
(define binds (request-bindings/raw req))
(define name (bindings-assq #"name" binds))
(define email (bindings-assq #"email" binds))
(response/xexpr
`(html
(head (title "表单提交结果"))
(body
(h1 "提交成功")
(p ,(format "姓名: ~a" (bytes->string/utf-8 (binding:form-value name))))
(p ,(format "邮箱: ~a" (bytes->string/utf-8 (binding:form-value email))))))))
JSON API
使用 json 库构建 RESTful API:
(require json)
(define (api-users req)
(response/json
#hasheq((users . (#hasheq((id . 1) (name . "Alice"))
#hasheq((id . 2) (name . "Bob")))))))
;; 辅助函数:返回 JSON 响应
(define (response/json data)
(response/full
200
#"OK"
(current-seconds)
APPLICATION/JSON-MIME-TYPE
'()
(list (jsexpr->bytes data))))
静态文件服务
(require web-server/dispatchers/dispatch-static)
;; 配置静态文件目录
(define static-dispatcher
(static-files-path "/path/to/static/files"))
部署
Racket Web 应用可以通过多种方式部署:
| 方式 | 说明 |
|---|---|
| 独立运行 | racket app.rkt 直接启动 |
| Docker | 打包为容器镜像 |
| Systemd | 配置为系统服务 |
| 反向代理 | 配合 Nginx 使用 |
;; 生产环境配置
(serve/servlet app
#:port (string->number (or (getenv "PORT") "8080"))
#:listen-ip #f
#:servlet-regexp #rx"")