server
Hello Cangjie
import net.http.ServerBuilder
main () {
// 1 Constructs a server instance.
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.build()
// 2 Registers the HttpRequestHandler.
server.distributor.register("/index", {httpContext =>
httpContext.responseBuilder.body("Hello Cangjie!")
})
// 3 Starts the service.
server.serve()
}
Registering a Handler Through the Request Distributor
import net.http.{ServerBuilder, HttpRequestHandler, FuncHandler}
main () {
// 1 Constructs a server instance.
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.build()
var a: HttpRequestHandler = FuncHandler({ httpContext =>
httpContext.responseBuilder.body("index")
})
var b: HttpRequestHandler = FuncHandler({ httpContext =>
httpContext.responseBuilder.body("id")
})
var c: HttpRequestHandler = FuncHandler({ httpContext =>
httpContext.responseBuilder.body("help")
})
server.distributor.register("/index", a)
server.distributor.register("/id", b)
server.distributor.register("/help", c)
// 2 Starts the service.
server.serve()
}
User-defined Request Distributor and Handler
import net.http.*
import std.collection.HashMap
class NaiveDistributor <: HttpRequestDistributor {
let map = HashMap<String, HttpRequestHandler>()
public func register(path: String, handler: HttpRequestHandler): Unit {
map.put(path, handler)
}
public func distribute(path: String): HttpRequestHandler {
if (path == "/index") {
return PageHandler()
}
return NotFoundHandler()
}
}
// Returns a simple HTML page.
class PageHandler <: HttpRequestHandler {
public func handle(httpContext: HttpContext): Unit {
httpContext.responseBuilder.body("<html></html>")
}
}
main () {
// 1 Constructs a server instance.
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.distributor(NaiveDistributor()) // User-defined distributor
.build()
// 2 Starts the service.
server.serve()
}
User-defined Server Network Configuration
import std.fs.*
import net.tls.*
import crypto.x509.{X509Certificate, PrivateKey}
import net.http.*
// This program can be executed only when an existing valid file path is configured.
main () {
// 1. User-defined configuration
// TCP configuration
var transportCfg = TransportConfig()
transportCfg.readBufferSize = 8192
// The matched certificate and private key file paths need to be input for TLS configuration.
let pem0 = String.fromUtf8(File("/certPath", OpenOption.Open(true, false)).readToEnd())
let pem02 = String.fromUtf8(File("/keyPath", OpenOption.Open(true, false)).readToEnd())
var tlsConfig = TlsServerConfig(X509Certificate.decodeFromPem(pem0), PrivateKey.decodeFromPem(pem02))
tlsConfig.supportedAlpnProtocols = ["h2"]
// 2 Constructs a server instance.
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.transportConfig(transportCfg)
.tlsConfig(tlsConfig)
.headerTableSize(10 * 1024)
.maxRequestHeaderSize(1024 * 1024)
.build()
// 3 Registers the HttpRequestHandler.
server.distributor.register("/index", {httpContext =>
httpContext.responseBuilder.body("Hello Cangjie!")
})
// 4 Starts the service.
server.serve()
}
chunked and trailer in the response
import net.http.*
import std.io.*
import std.collection.HashMap
func checksum(chunk: Array<UInt8>): Int64 {
var sum = 0
for (i in chunk) {
if (i == UInt8(UInt32(r'\n'))) {
sum += 1
}
}
return sum / 2
}
main () {
// 1 Constructs a server instance.
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.build()
// 2 Registers the HttpRequestHandler.
server.distributor.register("/index", {httpContext =>
let responseBuilder = httpContext.responseBuilder
responseBuilder.header("transfer-encoding", "chunked") // Sets the response header.
responseBuilder.header("trailer", "checkSum")
let writer = HttpResponseWriter(httpContext)
var sum = 0
for (_ in 0..10) {
let chunk = Array<UInt8>(10, item: 0)
sum += checksum(chunk)
writer.write(chunk) // Sends immediately.
}
responseBuilder.trailer("checkSum", "${sum}") // Sends after the handler ends.
})
// 3 Starts the service.
server.serve()
}
Processing the Redirection Request
import net.http.*
main () {
// 1 Constructs a server instance.
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.build()
// 2 Registers the HttpRequestHandler.
server.distributor.register("/redirecta",RedirectHandler("/movedsource", 308))
server.distributor.register("/redirectb",RedirectHandler("http://www.example.com", 308))
// 3 Starts the service.
server.serve()
}
TLS Certificate Hot Loading
import std.fs.*
import net.tls.*
import crypto.x509.{X509Certificate, PrivateKey}
import net.http.*
// This program can be executed only when an existing valid file path is configured.
main() {
// 1 TLS configuration
let pem0 = String.fromUtf8(File("/certPath", OpenOption.Open(true, false)).readToEnd())
let pem02 = String.fromUtf8(File("/keyPath", OpenOption.Open(true, false)).readToEnd())
var tlsConfig = TlsServerConfig(X509Certificate.decodeFromPem(pem0), PrivateKey.decodeFromPem(pem02))
tlsConfig.supportedAlpnProtocols = ["http/1.1"]
let pem = String.fromUtf8(File("/rootCerPath", OpenOption.Open(true, false)).readToEnd())
tlsConfig.verifyMode = CustomCA(X509Certificate.decodeFromPem(pem))
// 2 Constructs a server instance and starts the service.
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.tlsConfig(tlsConfig)
.build()
spawn {
server.serve()
}
// 3 Updates the TLS certificate and private key. The new certificate and private key are used for subsequent requests.
server.updateCert("/newCerPath", "/newKeyPath")
// 4 Updates the CA, which is used for two-way authentication. The new CA is used for subsequent requests.
server.updateCA("/newRootCerPath")
}
server push
Valid only for HTTP/2.
client:
import std.fs.*
import std.collection.ArrayList
import net.tls.*
import crypto.x509.X509Certificate
import net.http.*
// This program can be executed only when an existing valid file path is configured.
// client:
main() {
// 1 TLS configuration
var tlsConfig = TlsClientConfig()
let pem = String.fromUtf8(File("/rootCerPath", OpenOption.Open(true, false)).readToEnd())
tlsConfig.verifyMode = CustomCA(X509Certificate.decodeFromPem(pem))
tlsConfig.alpnProtocolsList = ["h2"]
// 2 Constructs a client instance.
let client = ClientBuilder()
.tlsConfig(tlsConfig)
.build()
// 3 Sends a request and receives a response.
let response = client.get("https://example.com/index.html")
// 4 Receives a pushResponse. In this example, it refers to the response of client.get("http://example.com/picture.png").
let pushResponses: Option<ArrayList<HttpResponse>> = response.getPush()
client.close()
}
server:
import std.fs.*
import net.tls.*
import crypto.x509.{X509Certificate, PrivateKey}
import net.http.*
// This program can be executed only when an existing valid file path is configured.
main() {
// 1 TLS configuration
let pem0 = String.fromUtf8(File("/certPath", OpenOption.Open(true, false)).readToEnd())
let pem02 = String.fromUtf8(File("/keyPath", OpenOption.Open(true, false)).readToEnd())
var tlsConfig = TlsServerConfig(X509Certificate.decodeFromPem(pem0), PrivateKey.decodeFromPem(pem02))
tlsConfig.supportedAlpnProtocols = ["h2"]
// 2 Constructs a server instance.
let server = ServerBuilder()
.addr("127.0.0.1")
.port(8080)
.tlsConfig(tlsConfig)
.build()
// 3 Registers the handler of the original request.
server.distributor.register("/index.html", {httpContext =>
let pusher = HttpResponsePusher.getPusher(httpContext)
match (pusher) {
case Some(pusher) =>
pusher.push("/picture.png", "GET", httpContext.request.headers)
case None =>
()
}
})
// 4 Registers the handler of pushRequest.
server.distributor.register("/picture.png", {httpContext =>
httpContext.responseBuilder.body("picture.png")
})
// 4 Starts the service.
server.serve()
}