added code to send CONNECT request for https requests through proxies, fixes #4520
This commit is contained in:
parent
27a40cd5a4
commit
56387c61dd
1 changed files with 52 additions and 16 deletions
|
|
@ -387,6 +387,8 @@ proc format(p: MultipartData): tuple[header, body: string] =
|
||||||
result.body.add("--" & bound & "\c\L" & s)
|
result.body.add("--" & bound & "\c\L" & s)
|
||||||
result.body.add("--" & bound & "--\c\L")
|
result.body.add("--" & bound & "--\c\L")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc request*(url: string, httpMethod: string, extraHeaders = "",
|
proc request*(url: string, httpMethod: string, extraHeaders = "",
|
||||||
body = "", sslContext = defaultSSLContext, timeout = -1,
|
body = "", sslContext = defaultSSLContext, timeout = -1,
|
||||||
userAgent = defUserAgent, proxy: Proxy = nil): Response =
|
userAgent = defUserAgent, proxy: Proxy = nil): Response =
|
||||||
|
|
@ -399,6 +401,55 @@ proc request*(url: string, httpMethod: string, extraHeaders = "",
|
||||||
var hostUrl = if proxy == nil: r else: parseUri(url)
|
var hostUrl = if proxy == nil: r else: parseUri(url)
|
||||||
var headers = substr(httpMethod, len("http"))
|
var headers = substr(httpMethod, len("http"))
|
||||||
# TODO: Use generateHeaders further down once it supports proxies.
|
# TODO: Use generateHeaders further down once it supports proxies.
|
||||||
|
|
||||||
|
var s = newSocket()
|
||||||
|
if s == nil: raiseOSError(osLastError())
|
||||||
|
var port = net.Port(80)
|
||||||
|
if r.scheme == "https":
|
||||||
|
when defined(ssl):
|
||||||
|
sslContext.wrapSocket(s)
|
||||||
|
port = net.Port(443)
|
||||||
|
else:
|
||||||
|
raise newException(HttpRequestError,
|
||||||
|
"SSL support is not available. Cannot connect over SSL.")
|
||||||
|
if r.port != "":
|
||||||
|
port = net.Port(r.port.parseInt)
|
||||||
|
|
||||||
|
|
||||||
|
# get the socket ready. If we are connecting through a proxy to SSL,
|
||||||
|
# send the appropiate CONNECT header. If not, simply connect to the proper
|
||||||
|
# host (which may still be the proxy, for normal HTTP)
|
||||||
|
if proxy != nil and hostUrl.scheme == "https":
|
||||||
|
var connectHeaders = "CONNECT "
|
||||||
|
let targetPort = if hostUrl.port == "": 443 else: hostUrl.port.parseInt
|
||||||
|
connectHeaders.add(hostUrl.hostname)
|
||||||
|
connectHeaders.add(":" & $targetPort)
|
||||||
|
connectHeaders.add(" HTTP/1.1\c\L")
|
||||||
|
connectHeaders.add("Host: " & hostUrl.hostname & ":" & $targetPort & "\c\L")
|
||||||
|
if proxy.auth != "":
|
||||||
|
let auth = base64.encode(proxy.auth, newline = "")
|
||||||
|
connectHeaders.add("Proxy-Authorization: basic " & auth & "\c\L")
|
||||||
|
connectHeaders.add("\c\L")
|
||||||
|
if timeout == -1:
|
||||||
|
s.connect(r.hostname, port)
|
||||||
|
else:
|
||||||
|
s.connect(r.hostname, port, timeout)
|
||||||
|
|
||||||
|
s.send(connectHeaders)
|
||||||
|
let connectResult = parseResponse(s, false, timeout)
|
||||||
|
if not connectResult.status.startsWith("200"):
|
||||||
|
raise newException(HttpRequestError,
|
||||||
|
"The proxy server rejected a CONNECT request, " &
|
||||||
|
"so a secure connection could not be established.")
|
||||||
|
sslContext.wrapConnectedSocket(s, handshakeAsClient)
|
||||||
|
else:
|
||||||
|
if timeout == -1:
|
||||||
|
s.connect(r.hostname, port)
|
||||||
|
else:
|
||||||
|
s.connect(r.hostname, port, timeout)
|
||||||
|
|
||||||
|
|
||||||
|
# now that the socket is ready, prepare the headers
|
||||||
if proxy == nil:
|
if proxy == nil:
|
||||||
headers.add ' '
|
headers.add ' '
|
||||||
if r.path[0] != '/': headers.add '/'
|
if r.path[0] != '/': headers.add '/'
|
||||||
|
|
@ -422,23 +473,8 @@ proc request*(url: string, httpMethod: string, extraHeaders = "",
|
||||||
add(headers, "Proxy-Authorization: basic " & auth & "\c\L")
|
add(headers, "Proxy-Authorization: basic " & auth & "\c\L")
|
||||||
add(headers, extraHeaders)
|
add(headers, extraHeaders)
|
||||||
add(headers, "\c\L")
|
add(headers, "\c\L")
|
||||||
var s = newSocket()
|
|
||||||
if s == nil: raiseOSError(osLastError())
|
|
||||||
var port = net.Port(80)
|
|
||||||
if r.scheme == "https":
|
|
||||||
when defined(ssl):
|
|
||||||
sslContext.wrapSocket(s)
|
|
||||||
port = net.Port(443)
|
|
||||||
else:
|
|
||||||
raise newException(HttpRequestError,
|
|
||||||
"SSL support is not available. Cannot connect over SSL.")
|
|
||||||
if r.port != "":
|
|
||||||
port = net.Port(r.port.parseInt)
|
|
||||||
|
|
||||||
if timeout == -1:
|
# headers are ready. send them, await the result, and close the socket.
|
||||||
s.connect(r.hostname, port)
|
|
||||||
else:
|
|
||||||
s.connect(r.hostname, port, timeout)
|
|
||||||
s.send(headers)
|
s.send(headers)
|
||||||
if body != "":
|
if body != "":
|
||||||
s.send(body)
|
s.send(body)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue