Fix redirection in httpclient (fixes #3895)

This commit is contained in:
def 2016-02-23 04:41:13 +01:00
commit 9afe2c1d8f

View file

@ -455,14 +455,15 @@ proc redirection(status: string): bool =
if status.startsWith(i): if status.startsWith(i):
return true return true
proc getNewLocation(lastUrl: string, headers: StringTableRef): string = proc getNewLocation(lastURL: string, headers: StringTableRef): string =
result = headers.getOrDefault"Location" result = headers.getOrDefault"Location"
if result == "": httpError("location header expected") if result == "": httpError("location header expected")
# Relative URLs. (Not part of the spec, but soon will be.) # Relative URLs. (Not part of the spec, but soon will be.)
let r = parseUri(result) let r = parseUri(result)
if r.hostname == "" and r.path != "": if r.hostname == "" and r.path != "":
let origParsed = parseUri(lastUrl) var parsed = parseUri(lastURL)
result = origParsed.hostname & "/" & r.path parsed.path = r.path
result = $parsed
proc get*(url: string, extraHeaders = "", maxRedirects = 5, proc get*(url: string, extraHeaders = "", maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext, sslContext: SSLContext = defaultSSLContext,
@ -481,7 +482,7 @@ proc get*(url: string, extraHeaders = "", maxRedirects = 5,
let redirectTo = getNewLocation(lastURL, result.headers) let redirectTo = getNewLocation(lastURL, result.headers)
result = request(redirectTo, httpGET, extraHeaders, "", sslContext, result = request(redirectTo, httpGET, extraHeaders, "", sslContext,
timeout, userAgent, proxy) timeout, userAgent, proxy)
lastUrl = redirectTo lastURL = redirectTo
proc getContent*(url: string, extraHeaders = "", maxRedirects = 5, proc getContent*(url: string, extraHeaders = "", maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext, sslContext: SSLContext = defaultSSLContext,
@ -528,14 +529,15 @@ proc post*(url: string, extraHeaders = "", body = "",
result = request(url, httpPOST, xh, xb, sslContext, timeout, userAgent, result = request(url, httpPOST, xh, xb, sslContext, timeout, userAgent,
proxy) proxy)
var lastUrl = "" var lastURL = url
for i in 1..maxRedirects: for i in 1..maxRedirects:
if result.status.redirection(): if result.status.redirection():
echo "lastURL: ", lastURL
let redirectTo = getNewLocation(lastURL, result.headers) let redirectTo = getNewLocation(lastURL, result.headers)
var meth = if result.status != "307": httpGet else: httpPost var meth = if result.status != "307": httpGet else: httpPost
result = request(redirectTo, meth, xh, xb, sslContext, timeout, result = request(redirectTo, meth, xh, xb, sslContext, timeout,
userAgent, proxy) userAgent, proxy)
lastUrl = redirectTo lastURL = redirectTo
proc postContent*(url: string, extraHeaders = "", body = "", proc postContent*(url: string, extraHeaders = "", body = "",
maxRedirects = 5, maxRedirects = 5,
@ -827,7 +829,7 @@ proc get*(client: AsyncHttpClient, url: string): Future[Response] {.async.} =
if result.status.redirection(): if result.status.redirection():
let redirectTo = getNewLocation(lastURL, result.headers) let redirectTo = getNewLocation(lastURL, result.headers)
result = await client.request(redirectTo, httpGET) result = await client.request(redirectTo, httpGET)
lastUrl = redirectTo lastURL = redirectTo
proc post*(client: AsyncHttpClient, url: string, body = "", multipart: MultipartData = nil): Future[Response] {.async.} = proc post*(client: AsyncHttpClient, url: string, body = "", multipart: MultipartData = nil): Future[Response] {.async.} =
## Connects to the hostname specified by the URL and performs a POST request. ## Connects to the hostname specified by the URL and performs a POST request.