http4k is a lightweight but fully-featured HTTP toolkit written in pure Kotlin that enables the serving and consuming of HTTP services in a functional and consistent way. http4k applications are just Kotlin functions. For example, here's a simple echo server:
val app:HttpHandler= { request:Request->Response(OK).body(request.body) }
val server = app.asServer(SunHttp(8000)).start()
http4k consists of a lightweight core library, http4k-core, providing a base HTTP implementation and Server/Client implementations based on the JDK classes. Further servers, clients, serverless, templating, websockets capabilities are then implemented in add-on modules. http4k apps can be simply mounted into a running Server, Serverless platform, or compiled to GraalVM and run as a super-lightweight binary.
Application as a Function: Based on the Twitter paper "Your Server as a Function", all HTTP services can be composed
of 2 types of simple function:
HttpHandler:(Request) -> Response - provides a remote call for processing a Request.
Filter:(HttpHandler) -> HttpHandler - adds Request/Response pre/post processing. These filters are composed to make stacks of reusable behaviour that can
then be applied to an HttpHandler.
Immutability: All entities in the library are immutable unless their function explicitly disallows this.
Symmetric: The HttpHandler interface is identical for both HTTP services and clients. This allows for simple offline testability of applications, as well as
plugging together of services without HTTP container being required.
Dependency-lite: Apart the from Kotlin StdLib, http4k-core module has ZERO dependencies and weighs in at ~1mb. Add-on modules only have dependencies required for specific implementation.
Testability Built by TDD enthusiasts, so supports super-easy mechanisms for both in-memory and port-based testing of:
individual endpoints
applications
websockets/sse
full suites of microservices
Portable Apps are completely portable across deployment platform in either a Server-based, Serverless or Native binaries.
Quickstart
Bored with reading already and just want to get coding? For the impatient, visit the http4k toolbox to generate a complete project from the wide variety of http4k modules.
Alternatively, read the quickstart or take a look at the examples repo, which showcases a variety of http4k use-cases and features.
Plug a standard HttpHandler into the AWS v2 SDKs. This massively simplifies testing and allows for sniffing of the exact traffic going to AWS - brilliant for debugging and building fakes.
Client filter to allow super-simple interaction with AWS services (via request signing)
Tooling to support operating http4k applications in orchestrated cloud environments such as Kubernetes and CloudFoundry. 12-factor configuration, dual-port servers and health checks such as liveness and readiness checking.
API for declaring and injecting failure modes into http4k applications, allowing modelling and hence answering of "what if" style questions to help understand how code fares under failure conditions such as latency and dying processes.
Ultra-lightweight Selenium WebDriver implementation for http4k application.
Example
This quick example is designed to convey the simplicity & features of http4k . See also the quickstart for the simplest possible starting point and demonstrates how to serve and consume HTTP services with dynamic routing.
To install, add these dependencies to your Gradle file:
packageguide.howto.readmeimportorg.http4k.client.OkHttpimportorg.http4k.core.Filterimportorg.http4k.core.HttpHandlerimportorg.http4k.core.Method.GETimportorg.http4k.core.Requestimportorg.http4k.core.Responseimportorg.http4k.core.Status.Companion.OKimportorg.http4k.core.thenimportorg.http4k.filter.CachingFiltersimportorg.http4k.routing.bindimportorg.http4k.routing.pathimportorg.http4k.routing.routesimportorg.http4k.server.Jettyimportorg.http4k.server.asServerfunmain() {
// we can bind HttpHandlers (which are just functions from Request -> Response) to paths/methods to create a Route,// then combine many Routes together to make another HttpHandlerval app:HttpHandler= routes(
"/ping" bind GET to { _:Request->Response(OK).body("pong!") },
"/greet/{name}" bind GET to { req:Request->val name:String?= req.path("name")
Response(OK).body("hello ${name ?:"anon!"}")
}
)
// call the handler in-memory without spinning up a serverval inMemoryResponse:Response= app(Request(GET, "/greet/Bob"))
println(inMemoryResponse)
// Produces:// HTTP/1.1 200 OK////// hello Bob// this is a Filter - it performs pre/post processing on a request or responseval timingFilter =Filter {
next:HttpHandler->
{
request:Request->val start =System.currentTimeMillis()
val response = next(request)
val latency =System.currentTimeMillis() - start
println("Request to ${request.uri} took ${latency}ms")
response
}
}
// we can "stack" filters to create reusable units, and then apply them to an HttpHandlerval compositeFilter =CachingFilters.Response.NoCache().then(timingFilter)
val filteredApp:HttpHandler= compositeFilter.then(app)
// only 1 LOC to mount an app and start it in a container
filteredApp.asServer(Jetty(9000)).start()
// HTTP clients are also HttpHandlers!val client:HttpHandler=OkHttp()
val networkResponse:Response= client(Request(GET, "http://localhost:9000/greet/Bob"))
println(networkResponse)
// Produces:// Request to /api/greet/Bob took 1ms// HTTP/1.1 200// cache-control: private, must-revalidate// content-length: 9// date: Thu, 08 Jun 2017 13:01:13 GMT// expires: 0// server: Jetty(9.3.16.v20170120)//// hello Bob
}
Ivan Moore for pairing on "BarelyMagical", a 50-line wrapper around utterlyidle to allow "Server as a Function"
Contributors
This project exists thanks to all the people who contribute.
Backers & Sponsors
If you use http4k in your project or enterprise and would like to support ongoing development, please consider becoming a backer or a sponsor. Sponsor logos will show up here with a link to your website.
请发表评论