Created
March 2, 2021 07:50
-
-
Save treeform/9d0e2fc9a4e8b6e1a1e7d571c01be403 to your computer and use it in GitHub Desktop.
Some code to do http chunked encoding.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
proc fetchStr(req: Request): (string, seq[string]) = | |
## Fetches a URL and returns header and chunks. | |
var socket = newSocket() | |
if req.url.scheme == "https": | |
var ctx = | |
try: | |
let caCertPath = getAppDir() / "cacert.pem" | |
if not fileExists(caCertPath): | |
writeFile(caCertPath, cacertData) | |
# let certFile = getCurrentDir() / "cacert.pem" | |
# echo certFile | |
# echo existsFile(certFile) | |
# newContext(verifyMode = CVerifyPeer, certFile = certFile) | |
newContext(verifyMode = CVerifyPeer) | |
except: | |
var message = getCurrentExceptionMsg() | |
raise newException(PuppyError, message) | |
#wrapSocket(ctx, socket) | |
socket.connect(req.url.hostname, Port(443)) | |
try: | |
ctx.wrapConnectedSocket( | |
socket, handshakeAsClient, req.url.hostname) | |
except: | |
var message = getCurrentExceptionMsg() | |
if "error:14094410:SSL" in message: | |
message = "Not Secure: Domain failed SSL certificate check." | |
raise newException(PuppyError, message) | |
else: | |
socket.connect(req.url.hostname, Port(80)) | |
socket.send($req) | |
var | |
chunked: bool | |
contentLength: int | |
var res = "" | |
while true: | |
let line = socket.recvLine() | |
res.add line & CRLF | |
let lineLower = line.toLowerAscii() | |
if line == CRLF: | |
break | |
elif lineLower.startsWith("content-length:"): | |
contentLength = parseInt(line.split(" ")[1]) | |
# elif lineLower.startsWith("x-uncompressed-content-length:"): | |
# contentLength = parseInt(line.split(" ")[1]) | |
elif lineLower == "transfer-encoding: chunked": | |
chunked = true | |
var chunks: seq[string] | |
if chunked: | |
while true: | |
var chunkLenStr: string | |
while true: | |
var readChar: char | |
let readLen = socket.recv(readChar.addr, 1) | |
doAssert readLen == 1 | |
chunkLenStr.add(readChar) | |
if chunkLenStr.endsWith(CRLF): | |
break | |
if chunkLenStr == CRLF: | |
break | |
var chunkLen: int | |
discard parseHex(chunkLenStr, chunkLen) | |
if chunkLen == 0: | |
break | |
var chunk = newString(chunkLen) | |
let readLen = socket.recv(chunk[0].addr, chunkLen) | |
doAssert readLen == chunkLen | |
chunks.add(chunk) | |
var endStr = newString(2) | |
let readLen2 = socket.recv(endStr[0].addr, 2) | |
doAssert endStr == CRLF | |
else: | |
var chunk = newString(contentLength) | |
let readLen = socket.recv(chunk[0].addr, contentLength) | |
doAssert readLen == contentLength | |
chunks.add(chunk[0..^3]) | |
return (res, chunks) | |
proc fetch(req: Request): Response = | |
let (resBody, chunks) = fetchStr(req) | |
var res = Response() | |
res.url = req.url | |
let resLines = resBody.split(CRLF) | |
let headerArr = resLines[0].split(" ") | |
res.code = parseInt(headerArr[1]) | |
res.body = join(chunks) | |
return res |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment