Merge pull request #5250 from yglukhov/http-redirect

Redirects support in request proc
This commit is contained in:
Dominik Picheta
2017-01-21 11:48:50 +01:00
committed by GitHub
3 changed files with 60 additions and 18 deletions

View File

@@ -540,6 +540,8 @@ proc getNewLocation(lastURL: string, headers: HttpHeaders): string =
if r.hostname == "" and r.path != "":
var parsed = parseUri(lastURL)
parsed.path = r.path
parsed.query = r.query
parsed.anchor = r.anchor
result = $parsed
proc get*(url: string, extraHeaders = "", maxRedirects = 5,
@@ -1000,15 +1002,10 @@ proc override(fallback, override: HttpHeaders): HttpHeaders =
for k, vs in override.table:
result[k] = vs
proc request*(client: HttpClient | AsyncHttpClient, url: string,
proc requestAux(client: HttpClient | AsyncHttpClient, url: string,
httpMethod: string, body = "",
headers: HttpHeaders = nil): Future[Response] {.multisync.} =
## Connects to the hostname specified by the URL and performs a request
## using the custom method string specified by ``httpMethod``.
##
## Connection will kept alive. Further requests on the same ``client`` to
## the same hostname will not require a new connection to be made. The
## connection can be closed by using the ``close`` procedure.
# 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)
@@ -1021,7 +1018,7 @@ proc request*(client: HttpClient | AsyncHttpClient, url: string,
var connectUrl = requestUrl
connectUrl.scheme = "http"
connectUrl.port = "443"
let proxyResp = await request(client, $connectUrl, $HttpConnect)
let proxyResp = await requestAux(client, $connectUrl, $HttpConnect)
if not proxyResp.status.startsWith("200"):
raise newException(HttpRequestError,
@@ -1053,6 +1050,29 @@ proc request*(client: HttpClient | AsyncHttpClient, url: string,
# 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] {.multisync.} =
## Connects to the hostname specified by the URL and performs a request
## using the custom method string specified by ``httpMethod``.
##
## Connection will kept alive. Further requests on the same ``client`` to
## the same hostname will not require a new connection to be made. The
## connection can be closed by using the ``close`` procedure.
##
## This procedure will follow redirects up to a maximum number of redirects
## specified in ``client.maxRedirects``.
result = await client.requestAux(url, httpMethod, body, headers)
var lastURL = url
for i in 1..client.maxRedirects:
if result.status.redirection():
let redirectTo = getNewLocation(lastURL, result.headers)
result = await client.request(redirectTo, httpMethod, body, headers)
lastURL = redirectTo
proc request*(client: HttpClient | AsyncHttpClient, url: string,
httpMethod = HttpGET, body = "",
headers: HttpHeaders = nil): Future[Response] {.multisync.} =
@@ -1076,14 +1096,6 @@ proc get*(client: HttpClient | AsyncHttpClient,
## specified in ``client.maxRedirects``.
result = await client.request(url, HttpGET)
# Handle redirects.
var lastURL = url
for i in 1..client.maxRedirects:
if result.status.redirection():
let redirectTo = getNewLocation(lastURL, result.headers)
result = await client.request(redirectTo, HttpGET)
lastURL = redirectTo
proc getContent*(client: HttpClient | AsyncHttpClient,
url: string): Future[string] {.multisync.} =
## Connects to the hostname specified by the URL and performs a GET request.
@@ -1119,7 +1131,7 @@ proc post*(client: HttpClient | AsyncHttpClient, url: string, body = "",
headers["Content-Type"] = mpHeader.split(": ")[1]
headers["Content-Length"] = $len(xb)
result = await client.request(url, HttpPOST, xb,
result = await client.requestAux(url, $HttpPOST, xb,
headers = headers)
# Handle redirects.
var lastURL = url
@@ -1127,7 +1139,7 @@ proc post*(client: HttpClient | AsyncHttpClient, url: string, body = "",
if result.status.redirection():
let redirectTo = getNewLocation(lastURL, result.headers)
var meth = if result.status != "307": HttpGet else: HttpPost
result = await client.request(redirectTo, meth, xb,
result = await client.requestAux(redirectTo, $meth, xb,
headers = headers)
lastURL = redirectTo

View File

@@ -2,6 +2,9 @@
News
====
`2017-01-08 Nim Version 0.16.2 released <news/e031_version_0_16_2.html>`_
===================================
`2017-01-08 Nim Version 0.16.0 released <news/e029_version_0_16_0.html>`_
===================================

View File

@@ -0,0 +1,27 @@
Version 0.16.2 released
=======================
Changelog
~~~~~~~~~
Changes affecting backwards compatibility
-----------------------------------------
- ``httpclient.request`` now respects ``maxRedirects`` option. Previously
redirects were handled only by ``get`` and ``post`` procs.
Library Additions
-----------------
Tool Additions
--------------
Compiler Additions
------------------
Language Additions
------------------