mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 23:33:28 +00:00
Remove old and unused parseBody/parseResponse procs in httpclient. (#11949)
This commit is contained in:
committed by
Andreas Rumpf
parent
ae9bb4474b
commit
8117a949c5
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2016 Dominik Picheta, Andreas Rumpf
|
||||
# (c) Copyright 2019 Nim Contributors
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -175,7 +175,7 @@
|
||||
## let client = newHttpClient(maxRedirects = 0)
|
||||
##
|
||||
|
||||
import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes,
|
||||
import net, strutils, uri, parseutils, base64, os, mimetypes,
|
||||
math, random, httpcore, times, tables, streams, std/monotimes
|
||||
import asyncnet, asyncdispatch, asyncfile
|
||||
import nativesockets
|
||||
@@ -276,134 +276,6 @@ proc fileError(msg: string) =
|
||||
e.msg = msg
|
||||
raise e
|
||||
|
||||
proc parseChunks(s: Socket, timeout: int): string =
|
||||
result = ""
|
||||
var ri = 0
|
||||
while true:
|
||||
var chunkSizeStr = ""
|
||||
var chunkSize = 0
|
||||
s.readLine(chunkSizeStr, timeout)
|
||||
var i = 0
|
||||
if chunkSizeStr == "":
|
||||
httpError("Server terminated connection prematurely")
|
||||
while i < chunkSizeStr.len:
|
||||
case chunkSizeStr[i]
|
||||
of '0'..'9':
|
||||
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('0'))
|
||||
of 'a'..'f':
|
||||
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('a') + 10)
|
||||
of 'A'..'F':
|
||||
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10)
|
||||
of ';':
|
||||
# http://tools.ietf.org/html/rfc2616#section-3.6.1
|
||||
# We don't care about chunk-extensions.
|
||||
break
|
||||
else:
|
||||
httpError("Invalid chunk size: " & chunkSizeStr)
|
||||
inc(i)
|
||||
if chunkSize <= 0:
|
||||
s.skip(2, timeout) # Skip \c\L
|
||||
break
|
||||
result.setLen(ri+chunkSize)
|
||||
var bytesRead = 0
|
||||
while bytesRead != chunkSize:
|
||||
let ret = recv(s, addr(result[ri]), chunkSize-bytesRead, timeout)
|
||||
ri += ret
|
||||
bytesRead += ret
|
||||
s.skip(2, timeout) # Skip \c\L
|
||||
# Trailer headers will only be sent if the request specifies that we want
|
||||
# them: http://tools.ietf.org/html/rfc2616#section-3.6.1
|
||||
|
||||
proc parseBody(s: Socket, headers: HttpHeaders, httpVersion: string, timeout: int): string =
|
||||
result = ""
|
||||
if headers.getOrDefault"Transfer-Encoding" == "chunked":
|
||||
result = parseChunks(s, timeout)
|
||||
else:
|
||||
# -REGION- Content-Length
|
||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3
|
||||
var contentLengthHeader = headers.getOrDefault"Content-Length"
|
||||
if contentLengthHeader != "":
|
||||
var length = contentLengthHeader.parseInt()
|
||||
if length > 0:
|
||||
result = newString(length)
|
||||
var received = 0
|
||||
while true:
|
||||
if received >= length: break
|
||||
let r = s.recv(addr(result[received]), length-received, timeout)
|
||||
if r == 0: break
|
||||
received += r
|
||||
if received != length:
|
||||
httpError("Got invalid content length. Expected: " & $length &
|
||||
" got: " & $received)
|
||||
else:
|
||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO
|
||||
|
||||
# -REGION- Connection: Close
|
||||
# (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5
|
||||
let implicitConnectionClose =
|
||||
httpVersion == "1.0" or
|
||||
# This doesn't match the HTTP spec, but it fixes issues for non-conforming servers.
|
||||
(httpVersion == "1.1" and headers.getOrDefault"Connection" == "")
|
||||
if headers.getOrDefault"Connection" == "close" or implicitConnectionClose:
|
||||
var buf = ""
|
||||
while true:
|
||||
buf = newString(4000)
|
||||
let r = s.recv(addr(buf[0]), 4000, timeout)
|
||||
if r == 0: break
|
||||
buf.setLen(r)
|
||||
result.add(buf)
|
||||
|
||||
proc parseResponse(s: Socket, getBody: bool, timeout: int): Response =
|
||||
new result
|
||||
var parsedStatus = false
|
||||
var linei = 0
|
||||
var fullyRead = false
|
||||
var line = ""
|
||||
result.headers = newHttpHeaders()
|
||||
while true:
|
||||
line = ""
|
||||
linei = 0
|
||||
s.readLine(line, timeout)
|
||||
if line == "": break # We've been disconnected.
|
||||
if line == "\c\L":
|
||||
fullyRead = true
|
||||
break
|
||||
if not parsedStatus:
|
||||
# Parse HTTP version info and status code.
|
||||
var le = skipIgnoreCase(line, "HTTP/", linei)
|
||||
if le <= 0: httpError("invalid http version")
|
||||
inc(linei, le)
|
||||
le = skipIgnoreCase(line, "1.1", linei)
|
||||
if le > 0: result.version = "1.1"
|
||||
else:
|
||||
le = skipIgnoreCase(line, "1.0", linei)
|
||||
if le <= 0: httpError("unsupported http version")
|
||||
result.version = "1.0"
|
||||
inc(linei, le)
|
||||
# Status code
|
||||
linei.inc skipWhitespace(line, linei)
|
||||
result.status = line[linei .. ^1]
|
||||
parsedStatus = true
|
||||
else:
|
||||
# Parse headers
|
||||
var name = ""
|
||||
var le = parseUntil(line, name, ':', linei)
|
||||
if le <= 0: httpError("invalid headers")
|
||||
inc(linei, le)
|
||||
if line[linei] != ':': httpError("invalid headers")
|
||||
inc(linei) # Skip :
|
||||
|
||||
result.headers.add(name, line[linei.. ^1].strip())
|
||||
# Ensure the server isn't trying to DoS us.
|
||||
if result.headers.len > headerLimit:
|
||||
httpError("too many headers")
|
||||
|
||||
if not fullyRead:
|
||||
httpError("Connection was closed before full request has been made")
|
||||
if getBody:
|
||||
result.body = parseBody(s, result.headers, result.version, timeout)
|
||||
else:
|
||||
result.body = ""
|
||||
|
||||
when not defined(ssl):
|
||||
type SSLContext = ref object
|
||||
|
||||
Reference in New Issue
Block a user