add http.cm and probe
This commit is contained in:
164
http.cm
Normal file
164
http.cm
Normal file
@@ -0,0 +1,164 @@
|
||||
var socket = use('socket')
|
||||
var c_http = use('net/http')
|
||||
|
||||
def CRLF = "\r\n"
|
||||
|
||||
def status_texts = {
|
||||
"200": "OK", "201": "Created", "204": "No Content",
|
||||
"400": "Bad Request", "401": "Unauthorized", "403": "Forbidden",
|
||||
"404": "Not Found", "405": "Method Not Allowed", "500": "Internal Server Error"
|
||||
}
|
||||
|
||||
function serve(port) {
|
||||
var fd = socket.socket("AF_INET", "SOCK_STREAM")
|
||||
socket.setsockopt(fd, "SOL_SOCKET", "SO_REUSEADDR", true)
|
||||
socket.bind(fd, {address: "127.0.0.1", port: port})
|
||||
socket.listen(fd, 16)
|
||||
return fd
|
||||
}
|
||||
|
||||
function parse_request(conn_fd) {
|
||||
var data = socket.recv(conn_fd, 65536)
|
||||
var raw = text(data)
|
||||
|
||||
var hdr_end = search(raw, CRLF + CRLF)
|
||||
if (hdr_end == null) disrupt
|
||||
var header_text = text(raw, 0, hdr_end)
|
||||
var body_text = text(raw, hdr_end + 4)
|
||||
|
||||
var lines = array(header_text, CRLF)
|
||||
var parts = array(lines[0], " ")
|
||||
var method = parts[0]
|
||||
var url = parts[1]
|
||||
var qpos = search(url, "?")
|
||||
var path = qpos != null ? text(url, 0, qpos) : url
|
||||
|
||||
var headers = {}
|
||||
var i = 1
|
||||
var colon = null
|
||||
var key = null
|
||||
var val = null
|
||||
while (i < length(lines)) {
|
||||
colon = search(lines[i], ": ")
|
||||
if (colon != null) {
|
||||
key = lower(text(lines[i], 0, colon))
|
||||
val = text(lines[i], colon + 2)
|
||||
headers[key] = val
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
var cl = headers["content-length"]
|
||||
var content_length = null
|
||||
var remaining = null
|
||||
var more = null
|
||||
if (cl != null) content_length = number(cl)
|
||||
if (content_length != null && length(body_text) < content_length) {
|
||||
remaining = content_length - length(body_text)
|
||||
more = socket.recv(conn_fd, remaining)
|
||||
body_text = body_text + text(more)
|
||||
}
|
||||
if (content_length == null || content_length == 0) body_text = null
|
||||
|
||||
return {
|
||||
method: method, path: path, url: url,
|
||||
headers: headers, body: body_text, _conn: conn_fd
|
||||
}
|
||||
}
|
||||
|
||||
function accept(server_fd) {
|
||||
var conn = socket.accept(server_fd)
|
||||
return parse_request(conn.socket)
|
||||
}
|
||||
|
||||
function on_request(server_fd, handler) {
|
||||
var _accept = function() {
|
||||
var conn = socket.accept(server_fd)
|
||||
var req = null
|
||||
var _parse = function() {
|
||||
req = parse_request(conn.socket)
|
||||
} disruption {
|
||||
req = null
|
||||
}
|
||||
_parse()
|
||||
if (req != null) handler(req)
|
||||
socket.on_readable(server_fd, _accept)
|
||||
}
|
||||
socket.on_readable(server_fd, _accept)
|
||||
}
|
||||
|
||||
function respond(conn, status, headers, body) {
|
||||
var st = status_texts[text(status)]
|
||||
if (st == null) st = "Unknown"
|
||||
var out = "HTTP/1.1 " + text(status) + " " + st + CRLF
|
||||
out = out + "Connection: close" + CRLF
|
||||
|
||||
var body_str = ""
|
||||
var keys = null
|
||||
var i = 0
|
||||
if (body != null) {
|
||||
if (is_text(body)) body_str = body
|
||||
else body_str = text(body)
|
||||
}
|
||||
|
||||
if (headers != null) {
|
||||
keys = array(headers)
|
||||
i = 0
|
||||
while (i < length(keys)) {
|
||||
out = out + keys[i] + ": " + headers[keys[i]] + CRLF
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
out = out + "Content-Length: " + text(length(body_str)) + CRLF
|
||||
out = out + CRLF + body_str
|
||||
|
||||
socket.send(conn, out)
|
||||
socket.close(conn)
|
||||
}
|
||||
|
||||
function sse_open(conn, headers) {
|
||||
var out = "HTTP/1.1 200 OK" + CRLF
|
||||
out = out + "Content-Type: text/event-stream" + CRLF
|
||||
out = out + "Cache-Control: no-cache" + CRLF
|
||||
out = out + "Connection: keep-alive" + CRLF
|
||||
var keys = null
|
||||
var i = 0
|
||||
if (headers != null) {
|
||||
keys = array(headers)
|
||||
i = 0
|
||||
while (i < length(keys)) {
|
||||
out = out + keys[i] + ": " + headers[keys[i]] + CRLF
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
out = out + CRLF
|
||||
socket.send(conn, out)
|
||||
}
|
||||
|
||||
function sse_event(conn, event, data) {
|
||||
var frame = "event: " + event + "\ndata: " + data + "\n\n"
|
||||
var ok = true
|
||||
var _send = function() {
|
||||
socket.send(conn, frame)
|
||||
} disruption {
|
||||
ok = false
|
||||
}
|
||||
_send()
|
||||
return ok
|
||||
}
|
||||
|
||||
function sse_close(conn) {
|
||||
socket.close(conn)
|
||||
}
|
||||
|
||||
function close(fd) {
|
||||
socket.close(fd)
|
||||
}
|
||||
|
||||
return {
|
||||
serve: serve, accept: accept, on_request: on_request,
|
||||
respond: respond,
|
||||
sse_open: sse_open, sse_event: sse_event, sse_close: sse_close,
|
||||
close: close, fetch: c_http.fetch
|
||||
}
|
||||
Reference in New Issue
Block a user