Remove old and unused parseBody/parseResponse procs in httpclient. (#11949)
This commit is contained in:
parent
ae9bb4474b
commit
8117a949c5
1 changed files with 2 additions and 130 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nim's Runtime Library
|
# Nim's Runtime Library
|
||||||
# (c) Copyright 2016 Dominik Picheta, Andreas Rumpf
|
# (c) Copyright 2019 Nim Contributors
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -175,7 +175,7 @@
|
||||||
## let client = newHttpClient(maxRedirects = 0)
|
## 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
|
math, random, httpcore, times, tables, streams, std/monotimes
|
||||||
import asyncnet, asyncdispatch, asyncfile
|
import asyncnet, asyncdispatch, asyncfile
|
||||||
import nativesockets
|
import nativesockets
|
||||||
|
|
@ -276,134 +276,6 @@ proc fileError(msg: string) =
|
||||||
e.msg = msg
|
e.msg = msg
|
||||||
raise e
|
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):
|
when not defined(ssl):
|
||||||
type SSLContext = ref object
|
type SSLContext = ref object
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue