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()
}