Hexaville框架

这是用于 Hexaville 的应用程序框架层

所有 Hexaville 应用程序都应该使用此框架编写。

目录

用法

import HexavilleFramework

let app = HexavilleFramework()

app.use(RandomNumberGenerateMiddleware())

let router = Router()

router.use(.get, "/") { request, context in
    let htmlString = "<html><head><title>Hexaville</title></head><body>Welcome to Hexaville!</body></html>"
    return Response(headers: ["Content-Type": "text/html"], body: htmlString)
}

app.use(router)

try app.run()

路由

基本路由

let app = HexavilleFramework()

let router = Router()

router.use(.get, "/hello") { response, context in
    return Response(body: "Hello")
}

app.use(router)

带有中间件的路由

let app = HexavilleFramework()

let router = Router()

router.use(.get, middlewares: [RandomNumberGenerateMiddleware()], "/hello") { response, context in
    return Response(body: "Random number is \(context["randomNumber"])")
}

app.use(router)

中间件

您可以创建自己的中间件来遵循 Middleware 协议。

enum JWTAuthenticationMiddleware {
    case authrozationHeaderIsMissing
}

struct JWTAuthenticationMiddleware: Middleware {
    func respond(to request: Request, context: ApplicationContext) throws -> Chainer {
        guard let jwtString = request.headers["Authorization"] else {
            throw JWTAuthenticationMiddleware.authrozationHeaderIsMissing
        }
        
        let jwt = try JWT.decode(jwtString)
        
        context.memory["JWT"] = jwt
        
        return .next(request)
    }
}

app.use(JWTAuthenticationMiddleware())

应用程序上下文 (ApplicationContext)

ApplicationContext 是请求的共享存储。

可用属性

memory (内存)

memory 属性用于在中间件和路由器之间共享值。

struct FooMiddleware: Middleware {
    func respond(to request: Request, context: ApplicationContext) throws -> Chainer {
        context.memory["Foo"] = "Bar"
        return .next(request)
    }
}

app.use(.get, middlewares: [FooMiddleware()], "/foo") { request, context in
    print(context["Foo"]) // Bar
}

responseHeaders (响应头)

在某些中间件中,您可能想要预设响应头,例如 Set-Cookie。通过将 HTTP 标头预设到 responseHeaders 属性中,标头值将自动添加到框架端的实际响应中。

这是一个示例。

struct CookieSetMiddleware: Middleware {
    func respond(to request: Request, context: ApplicationContext) throws -> Chainer {
        context.responseHeaders["Set-Cookie"] = "vaild cookie value"
        return .next(request)
    }
}

app.use(.get, middlewares: [FooMiddleware()], "/foo") { request, context in
    return Response(body: "OK")
}

响应

HTTP/1.1 200

Set-Cookie: vaild cookie value

OK

session (会话)

session 属性用于应用程序中使用的数据持久化。 有关详细信息,请参阅 会话 (Session)

会话 (Session)

HexavilleFramework 通过 SessionMiddleware 提供会话机制。 您可以创建自己的 SessionStore 来遵循 SessionStoreProvider 协议。

捆绑的会话存储是 MemoryStore

可用的会话存储

用法

let session = SessionMiddleware(
    cookieAttribute: CookieAttribute(
        expiration: 3600,
        httpOnly: true,
        secure: false
    ),
    store: MemoryStore()
)

app.use(session)

app.use { request, context in
    // add value to session(memory)
    context.session["user"] = User(name: "Luke", age: 25).serializeToJSONString()
}

var router = Router()

// take value from context.session
router.use(.get, "/") { request, context in
    return Response(body: context.session["user"]!)
}

错误处理

您可以捕获会话中抛出的所有错误,使用 catch 错误处理程序。 在 catch 闭包中,确定错误响应的最佳方法是针对 Error 进行模式匹配。

let app = HexavilleFramework()

app.use(.....)

app.catch { error in
    switch error {
    case FooError.notFound:
        return Response(status: .notFound)
    case JWTAuthenticationMiddleware.authrozationHeaderIsMissing:
        return Response(status: .unauthorized)
    default:
        return Response(status: .internalServerError)
    }
}

try app.run()

如何部署?

请参阅 Hexaville 文档

内置 Web 服务器

您可以使用内置的 Web 服务器和 serve 命令来调试您的应用程序。

YourApplication/.build/debug/YourApplication serve
# => Hexaville Builtin Server started at 0.0.0.0:3000

许可证

HexavilleFramework 是在 MIT 许可证下发布的。 有关详细信息,请参阅 LICENSE 文件。