diff options
Diffstat (limited to 'lib/pure/httpclient.nim')
-rw-r--r-- | lib/pure/httpclient.nim | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index de1d332a3..54a8498fa 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -469,7 +469,7 @@ proc request*(url: string, httpMethod: string, extraHeaders = "", ## **Deprecated since version 0.15.0**: use ``HttpClient.request`` instead. var r = if proxy == nil: parseUri(url) else: proxy.url var hostUrl = if proxy == nil: r else: parseUri(url) - var headers = httpMethod.toUpper() + var headers = httpMethod.toUpperAscii() # TODO: Use generateHeaders further down once it supports proxies. var s = newSocket() @@ -713,10 +713,10 @@ proc downloadFile*(url: string, outputFilename: string, proc generateHeaders(requestUrl: Uri, httpMethod: string, headers: HttpHeaders, body: string, proxy: Proxy): string = # GET - result = httpMethod.toUpper() + result = httpMethod.toUpperAscii() result.add ' ' - if proxy.isNil: + if proxy.isNil or (not proxy.isNil and requestUrl.scheme == "https"): # /path?query if requestUrl.path[0] != '/': result.add '/' result.add(requestUrl.path) @@ -1048,7 +1048,11 @@ proc newConnection(client: HttpClient | AsyncHttpClient, client.currentURL.scheme != url.scheme or client.currentURL.port != url.port or (not client.connected): - let isSsl = url.scheme.toLowerAscii() == "https" + # Connect to proxy if specified + let connectionUrl = + if client.proxy.isNil: url else: client.proxy.url + + let isSsl = connectionUrl.scheme.toLowerAscii() == "https" if isSsl and not defined(ssl): raise newException(HttpRequestError, @@ -1056,31 +1060,55 @@ proc newConnection(client: HttpClient | AsyncHttpClient, if client.connected: client.close() + client.connected = false # TODO: I should be able to write 'net.Port' here... let port = - if url.port == "": + if connectionUrl.port == "": if isSsl: nativesockets.Port(443) else: nativesockets.Port(80) - else: nativesockets.Port(url.port.parseInt) + else: nativesockets.Port(connectionUrl.port.parseInt) when client is HttpClient: - client.socket = await net.dial(url.hostname, port) + client.socket = await net.dial(connectionUrl.hostname, port) elif client is AsyncHttpClient: - client.socket = await asyncnet.dial(url.hostname, port) + client.socket = await asyncnet.dial(connectionUrl.hostname, port) else: {.fatal: "Unsupported client type".} when defined(ssl): if isSsl: try: client.sslContext.wrapConnectedSocket( - client.socket, handshakeAsClient, url.hostname) + client.socket, handshakeAsClient, connectionUrl.hostname) except: client.socket.close() raise getCurrentException() + # If need to CONNECT through proxy + if url.scheme == "https" and not client.proxy.isNil: + when defined(ssl): + # Pass only host:port for CONNECT + var connectUrl = initUri() + connectUrl.hostname = url.hostname + connectUrl.port = if url.port != "": url.port else: "443" + + let proxyHeaderString = generateHeaders(connectUrl, $HttpConnect, newHttpHeaders(), "", client.proxy) + await client.socket.send(proxyHeaderString) + let proxyResp = await parseResponse(client, false) + + if not proxyResp.status.startsWith("200"): + raise newException(HttpRequestError, + "The proxy server rejected a CONNECT request, " & + "so a secure connection could not be established.") + client.sslContext.wrapConnectedSocket( + client.socket, handshakeAsClient, url.hostname) + else: + raise newException(HttpRequestError, + "SSL support is not available. Cannot connect over SSL.") + + # May be connected through proxy but remember actual URL being accessed client.currentURL = url client.connected = true @@ -1100,32 +1128,9 @@ proc requestAux(client: HttpClient | AsyncHttpClient, url: string, headers: HttpHeaders = nil): Future[Response | AsyncResponse] {.multisync.} = # Helper that actually makes the request. Does not handle redirects. - let connectionUrl = - if client.proxy.isNil: parseUri(url) else: client.proxy.url let requestUrl = parseUri(url) - let savedProxy = client.proxy # client's proxy may be overwritten. - - if requestUrl.scheme == "https" and not client.proxy.isNil: - when defined(ssl): - client.proxy.url = connectionUrl - var connectUrl = requestUrl - connectUrl.scheme = "http" - connectUrl.port = "443" - let proxyResp = await requestAux(client, $connectUrl, $HttpConnect) - - if not proxyResp.status.startsWith("200"): - raise newException(HttpRequestError, - "The proxy server rejected a CONNECT request, " & - "so a secure connection could not be established.") - client.sslContext.wrapConnectedSocket( - client.socket, handshakeAsClient, requestUrl.hostname) - client.proxy = nil - else: - raise newException(HttpRequestError, - "SSL support not available. Cannot connect to https site over proxy.") - else: - await newConnection(client, connectionUrl) + await newConnection(client, requestUrl) let effectiveHeaders = client.headers.override(headers) @@ -1143,9 +1148,6 @@ proc requestAux(client: HttpClient | AsyncHttpClient, url: string, client.getBody result = await parseResponse(client, getBody) - # Restore the clients proxy in case it was overwritten. - client.proxy = savedProxy - proc request*(client: HttpClient | AsyncHttpClient, url: string, httpMethod: string, body = "", headers: HttpHeaders = nil): Future[Response | AsyncResponse] |