about summary refs log tree commit diff stats
path: root/config.def.h
Commit message (Expand)AuthorAgeFilesLines
* removed all defines of geoms, implemented setgeoms() instead, added config.an...Anselm R Garbe2008-03-131-34/+0
* changed config.def.hAnselm R Garbe2008-03-061-2/+2
* new stuffAnselm R Garbe2008-03-061-4/+6
* implemented setlayout in the way proposed on the ml, split tile() into two fu...Anselm R Garbe2008-03-061-17/+17
* changed config.def.hAnselm R Garbe2008-03-051-32/+9
* integrated the new -x -y -w toggles of dmenu into my setupAnselm R Garbe2008-03-051-1/+6
* implemented the stuff as I discussed on dwm@Anselm R Garbe2008-03-051-6/+55
* renamed maximise to monocle again.Anselm R Garbe2008-03-051-4/+2
* renamed MAXLEN into MAXTAGLEN (backward compliance)anselm@anselm12008-03-041-1/+1
* renamed monocle into maxmise, documented the keybindings in dwm(1)anselm@anselm12008-03-041-5/+7
* monocle goes mainstreamAnselm R Garbe2008-03-041-1/+3
* removed View cruft, now back to the rootsanselm@anselm12008-03-031-1/+0
* made tag names snappierAnselm R Garbe2008-02-291-1/+1
* removed initags -- we autoselect the first tag in each view insteadanselm@anselm12008-02-281-1/+0
* some more changes towards a better dwmAnselm R Garbe2008-02-281-1/+1
* proceeded, though we still miss a real Tag structanselm@anselm12008-02-271-2/+4
* disabled AIM_XINERAMAanselm@anselm12008-02-261-1/+1
* simplified dwmanselm@anselm12008-02-261-2/+2
* pushing my changes of tonight upstream (hg tip is NOW very UNSTABLE -- but th...anselm@anselm12008-02-231-7/+7
* changed arrange functions to contain the Monitor as first argumentAnselm R Garbe2008-02-211-1/+1
* proceeded with multihead/Xinerama supportanselm@anselm12007-12-221-5/+5
* removed maximize, there will be monocle soonanselm@anselm12007-12-221-1/+0
* fixed wrong tagging stuffanselm@anselm12007-12-221-1/+1
* added dmenu_run to config.hanselm@anselm12007-12-221-2/+1
* simplified Mod-mAnselm R. Garbe2007-12-091-1/+1
* implemented reapply for re-applying the tagging rules during runtime, Mod-rAnselm R. Garbe2007-12-081-0/+1
* Using a new tags definition (const char [][MAXTAGLEN] - thanks go to Szabolcs!Anselm R. Garbe2007-11-101-58/+57
* moved LENGTH to dwm.c, moved prevtags to dwm.carg@suckless.org2007-11-071-4/+0
* revival of RESIZEHINTSAnselm R. Garbe2007-11-021-0/+1
* replaced Nmacros with LENGTH(x) macroAnselm R. Garbe2007-10-281-6/+5
* replaced ISTILE with domwfact/dozoom bools, removed nrules, nlayouts and ltid...Anselm R. Garbe2007-10-281-1/+3
* going toward 4.7Anselm R. Garbe2007-10-271-0/+3
* removed RESIZEHINTS and enhanced tile for fixed or aspect-ratio'ed clientsarg@suckless.org2007-10-241-1/+0
* added antoszka's viewprev patch with some minor modifications, restored Clien...Anselm R. Garbe2007-10-101-0/+1
* removing NULL-terminating **tags definition in config.hAnselm R. Garbe2007-10-051-1/+1
* s/xterm/uxterm/Anselm R. Garbe2007-10-011-1/+1
* fixed font definitionAnselm R. Garbe2007-10-011-1/+1
* applied Peter Hartlich's border collapse patchAnselm R. Garbe2007-09-301-7/+7
* fixed colorsAnselm R. Garbe2007-09-271-3/+3
* updated with my favorite colorschemeAnselm R. Garbe2007-09-261-7/+6
* applied colors depend from lavishs proposalAnselm R. Garbe2007-09-251-6/+6
* switching to white normal bg, renaming tag 9 into www, for static use in conj...Anselm R. Garbe2007-09-231-9/+9
* renamed config.h into config.def.h, config.h will be created if not present, ...Anselm R. Garbe2007-09-231-0/+94
span> "404 Not Found", Http500 = "500 Internal Server Error", Http502 = "502 Bad Gateway" THttpVersion* = enum HttpVer11, HttpVer10 proc `==`*(protocol: tuple[orig: string, major, minor: int], ver: THttpVersion): bool = let major = case ver of HttpVer11, HttpVer10: 1 let minor = case ver of HttpVer11: 1 of HttpVer10: 0 result = protocol.major == major and protocol.minor == minor proc newAsyncHttpServer*(): PAsyncHttpServer = new result proc sendHeaders*(req: TRequest, headers: PStringTable) {.async.} = ## Sends the specified headers to the requesting client. for k, v in headers: await req.client.send(k & ": " & v & "\c\L") proc respond*(req: TRequest, code: THttpCode, content: string, headers: PStringTable = newStringTable()) {.async.} = ## Responds to the request with the specified ``HttpCode``, headers and ## content. ## ## This procedure will **not** close the client socket. var customHeaders = headers customHeaders["Content-Length"] = $content.len await req.client.send("HTTP/1.1 " & $code & "\c\L") await sendHeaders(req, headers) await req.client.send("\c\L" & content) proc newRequest(): TRequest = result.headers = newStringTable(modeCaseInsensitive) proc parseHeader(line: string): tuple[key, value: string] = var i = 0 i = line.parseUntil(result.key, ':') inc(i) # skip : i += line.skipWhiteSpace(i) i += line.parseUntil(result.value, {'\c', '\L'}, i) proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] = var i = protocol.skipIgnoreCase("HTTP/") if i != 5: raise newException(EInvalidValue, "Invalid request protocol. Got: " & protocol) result.orig = protocol i.inc protocol.parseInt(result.major, i) i.inc # Skip . i.inc protocol.parseInt(result.minor, i) proc sendStatus(client: PAsyncSocket, status: string): PFuture[void] = client.send("HTTP/1.1 " & status & "\c\L") proc processClient(client: PAsyncSocket, address: string, callback: proc (request: TRequest): PFuture[void]) {.async.} = # GET /path HTTP/1.1 # Header: val # \n var request = newRequest() request.hostname = address assert client != nil request.client = client var runCallback = true # First line - GET /path HTTP/1.1 let line = await client.recvLine() # TODO: Timeouts. if line == "": client.close() return let lineParts = line.split(' ') if lineParts.len != 3: request.respond(Http400, "Invalid request. Got: " & line) runCallback = false let reqMethod = lineParts[0] let path = lineParts[1] let protocol = lineParts[2] # Headers var i = 0 while true: i = 0 let headerLine = await client.recvLine() if headerLine == "": client.close(); return if headerLine == "\c\L": break # TODO: Compiler crash #let (key, value) = parseHeader(headerLine) let kv = parseHeader(headerLine) request.headers[kv.key] = kv.value request.reqMethod = reqMethod request.url = parseUrl(path) try: request.protocol = protocol.parseProtocol() except EInvalidValue: request.respond(Http400, "Invalid request protocol. Got: " & protocol) runCallback = false if reqMethod.normalize == "post": # Check for Expect header if request.headers.hasKey("Expect"): if request.headers["Expect"].toLower == "100-continue": await client.sendStatus("100 Continue") else: await client.sendStatus("417 Expectation Failed") # Read the body # - Check for Content-length header if request.headers.hasKey("Content-Length"): var contentLength = 0 if parseInt(request.headers["Content-Length"], contentLength) == 0: await request.respond(Http400, "Bad Request. Invalid Content-Length.") else: request.body = await client.recv(contentLength) assert request.body.len == contentLength else: await request.respond(Http400, "Bad Request. No Content-Length.") runCallback = false case reqMethod.normalize of "get", "post", "head", "put", "delete", "trace", "options", "connect", "patch": if runCallback: await callback(request) else: await request.respond(Http400, "Invalid request method. Got: " & reqMethod) # Persistent connections if (request.protocol == HttpVer11 and request.headers["connection"].normalize != "close") or (request.protocol == HttpVer10 and request.headers["connection"].normalize == "keep-alive"): # In HTTP 1.1 we assume that connection is persistent. Unless connection # header states otherwise. # In HTTP 1.0 we assume that the connection should not be persistent. # Unless the connection header states otherwise. await processClient(client, address, callback) else: request.client.close() proc serve*(server: PAsyncHttpServer, port: TPort, callback: proc (request: TRequest): PFuture[void], address = "") {.async.} = ## Starts the process of listening for incoming HTTP connections on the ## specified address and port. ## ## When a request is made by a client the specified callback will be called. server.socket = newAsyncSocket() server.socket.bindAddr(port, address) server.socket.listen() while true: # TODO: Causes compiler crash. #var (address, client) = await server.socket.acceptAddr() var fut = await server.socket.acceptAddr() processClient(fut.client, fut.address, callback) proc close*(server: PAsyncHttpServer) = ## Terminates the async http server instance. server.socket.close() when isMainModule: var server = newAsyncHttpServer() proc cb(req: TRequest) {.async.} = #echo(req.reqMethod, " ", req.url) #echo(req.headers) let headers = {"Date": "Tue, 29 Apr 2014 23:40:08 GMT", "Content-type": "text/plain; charset=utf-8"} await req.respond(Http200, "Hello World", headers.newStringTable()) server.serve(TPort(5555), cb) runForever()