threading.Serve
Starts an HTTP, TCP or WebSocket (over HTTP) service inside the strategy process and returns a Server object.
Serve(serveURI, handler)
Serve(serveURI, handler, ...args)Examples
-
Start an HTTP service and request it from the main thread.
javascriptfunction main() { var server = threading.Serve("http://127.0.0.1:8088", function (ctx) { ctx.write("hello " + ctx.path()) }) Log("serve on", server.addr()) // Output: serve on 127.0.0.1:8088 Log(HttpQuery("http://127.0.0.1:8088/ping")) // Output: hello /ping server.close() } -
Start an HTTP service (with WebSocket) and a TCP echo service in one process, then test each.
javascriptfunction main() { let httpServer = threading.Serve("http://:8088?gzip=true", function (ctx) { Log("http connect from: ", ctx.remoteAddr(), "->", ctx.localAddr()) let path = ctx.path() if (path == "/") { ctx.write(JSON.stringify({ path: ctx.path(), method: ctx.method(), headers: ctx.headers(), cookie: ctx.header("Cookie"), remote: ctx.remoteAddr(), query: ctx.rawQuery() })) } else if (path == "/tickers") { let ret = exchange.GetTickers() if (!ret) { ctx.setStatus(500) ctx.write(GetLastError()) } else { ctx.write(JSON.stringify(ret)) } } else if (path == "/wss") { if (ctx.upgrade("websocket")) { // upgrade to websocket while (true) { let r = ctx.read(10) if (r == "") { break } else if (r) { if (r == "ticker") { ctx.write(JSON.stringify(exchange.GetTicker())) } else { ctx.write("not support") } } } Log("websocket closed", ctx.remoteAddr()) } } else { ctx.setStatus(404) } }) let echoServer = threading.Serve("tcp://:8089", function (ctx) { Log("tcp connect from: ", ctx.remoteAddr(), "->", ctx.localAddr()) while (true) { let d = ctx.read() if (!d) { break } ctx.write(d) } Log("connect closed") }) Log("http serve on", httpServer.addr(), "tcp serve on", echoServer.addr()) for (var i = 0; i < 5; i++) { if (i == 2) { // test Http var retHttp = HttpQuery("http://127.0.0.1:8088?num=123&limit=100", {"debug": true}) Log("retHttp:", retHttp) } else if (i == 3) { // test TCP var tcpConn = Dial("tcp://127.0.0.1:8089") tcpConn.write("Hello TCP Server") var retTCP = tcpConn.read() Log("retTCP:", retTCP) } else if (i == 4) { // test Websocket var wsConn = Dial("ws://127.0.0.1:8088/wss|compress=gzip") wsConn.write("ticker") var retWS = wsConn.read(1000) Log("retWS:", retWS) // no depth wsConn.write("depth") retWS = wsConn.read(1000) Log("retWS:", retWS) } Sleep(1000) } httpServer.close() echoServer.close() }
Returns
| Type | Description |
| A |
Arguments
| Name | Type | Required | Description |
serveURI | string | Yes | Protocol, bind address, port and options of the service, for example |
handler | function | Yes | Route handler (HTTP), message handler (TCP) or stream handler (WebSocket). It is called once per TCP connection or HTTP request, each in its own thread. |
arg | string / number / bool / object / array / function / any | No | Extra arguments passed to the |
See Also
Remarks
- JavaScript strategies only.
- Like threads created by
Thread, the handler runs in an isolated environment: it cannot reference outer variables, closures or user-defined functions, so pass what it needs through...args; every platform API is available. Objects such asThreadDictandThreadLockcan be passed as arguments to share data with other threads. - An HTTP service handles one request per connection; what the handler writes with
ctx.write()is sent in one piece after the handler returns. - At most 64 handlers run at the same time per service; beyond that HTTP requests get
503and TCP connections are dropped. - Services close automatically when the strategy stops; call
close()orstop()on the returned object to close one earlier. - WebSocket services are built on HTTP: route one path to the WebSocket handler to implement subscription/push, as in the example in this section.
- The old global function
__Serve()still works with the same arguments but returns only the listening address string, i.e.threading.Serve(...).addr(); usethreading.Serve()in new code.
The callback passed as handler receives a ctx parameter, a context object for reading request data and writing responses, with the following methods:
- ctx.proto()
HTTP/TCP. Returns the protocol name, for exampleHTTP/1.1ortcp. - ctx.host()
HTTP. Returns the host information: IP address and port. - ctx.path()
HTTP. Returns the request path. - ctx.query(key)
HTTP. Returns the value ofkeyin the request's query string. For the requesthttp://127.0.0.1:8088?num=123,ctx.query("num")returns"123". - ctx.rawQuery()
HTTP. Returns the raw query string of the request. - ctx.headers()
HTTP. Returns the request headers. - ctx.header(key)
HTTP. Returns the value of one request header, for examplectx.header("User-Agent"). - ctx.method()
HTTP. Returns the request method, such asGETorPOST. - ctx.body()
HTTP POST. Returns the request body. - ctx.setHeader(key, value)
HTTP. Sets a response header. - ctx.setStatus(code)
HTTP. Sets the response status code, usually at the end of a route branch; the default is 200. - ctx.remoteAddr()
HTTP/TCP. Returns the address and port of the remote client. - ctx.localAddr()
HTTP/TCP. Returns the local address and port of the service. - ctx.upgrade("websocket")
WebSocket over HTTP. Switchesctxto the WebSocket protocol; returnstrueon success andfalseon failure. - ctx.read(timeout_ms)
WebSocket and TCP (not plain HTTP). Reads data from the connection;timeout_msis an optional timeout in milliseconds. Returnsnullon timeout and an empty string""when the peer closed the connection. - ctx.write(s)
HTTP/TCP. Writes string data; encode objects withJSON.stringify()first. On a WebSocket connection it sends the string to the client.
Writing serveURI:
- Only the
tcp://(TCP service) andhttp://(HTTP service) prefixes are accepted. WebSocket services usehttp://too: callctx.upgrade("websocket")in the handler to switch. - The IP can be omitted, as in
http://:8088(listen on all interfaces); port0picks a free port, andaddr()on the returned object gives the actual address. - Options after
?:gzip=true(gzip compression) andtls=true(TLS: HTTPS, wss, or TLS over TCP). With TLS the PEM certificate and private key must be given as well, URL-encoded, incert_pemandcert_key_pem, for examplehttp://:8443?tls=true&cert_pem=xxxx&cert_key_pem=xxxx; an HTTPS service ishttp://withtls=true.
Using arg: the arguments 1, 2, 3 passed to Serve() below become the callback parameters a, b, c.
javascript
threading.Serve("http://:8088", function(ctx, a, b, c) {
Log(`ctx.host():`, ctx.host(), ", a=", a, ", b=", b, ", c=", c)
}, 1, 2, 3)