Skip to content
This repository was archived by the owner on Apr 4, 2022. It is now read-only.

Commit cbced01

Browse files
committed
Follow redirects across schemes
HttpURLConnection doesn't follow redirects from http <-> https so I added some manual handling. closes #92
1 parent 59a2073 commit cbced01

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

src/main/scala/scalaj/http/Http.scala

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,14 @@ case class HttpRequest(
332332
* @param parser function to process the response body InputStream
333333
*/
334334
def exec[T](parser: (Int, Map[String, IndexedSeq[String]], InputStream) => T): HttpResponse[T] = {
335-
val urlToFetch: URL = new URL(urlBuilder(this))
335+
doConnection(parser, new URL(urlBuilder(this)), connectFunc)
336+
}
337+
338+
private def doConnection[T](
339+
parser: (Int, Map[String, IndexedSeq[String]], InputStream) => T,
340+
urlToFetch: URL,
341+
connectFunc: (HttpRequest, HttpURLConnection) => Unit
342+
): HttpResponse[T] = {
336343
proxyConfig.map(urlToFetch.openConnection).getOrElse(urlToFetch.openConnection) match {
337344
case conn: HttpURLConnection =>
338345
conn.setInstanceFollowRedirects(false)
@@ -365,16 +372,23 @@ case class HttpRequest(
365372
val responseCode: Int = conn.getResponseCode
366373
val headers: Map[String, IndexedSeq[String]] = getResponseHeaders(conn)
367374
val encoding: Option[String] = headers.get("Content-Encoding").flatMap(_.headOption)
368-
val body: T = {
369-
val shouldDecompress = compress && inputStream != null
370-
val theStream = if (shouldDecompress && encoding.exists(_.equalsIgnoreCase("gzip"))) {
371-
new GZIPInputStream(inputStream)
372-
} else if(shouldDecompress && encoding.exists(_.equalsIgnoreCase("deflate"))) {
373-
new InflaterInputStream(inputStream)
374-
} else inputStream
375-
parser(responseCode, headers, theStream)
375+
// HttpURLConnection won't redirect from https <-> http, so we handle manually here
376+
(if (conn.getInstanceFollowRedirects && (responseCode == 301 || responseCode == 302)) {
377+
headers.get("Location").flatMap(_.headOption).map(location => {
378+
doConnection(parser, new URL(location), DefaultConnectFunc)
379+
})
380+
} else None).getOrElse{
381+
val body: T = {
382+
val shouldDecompress = compress && inputStream != null
383+
val theStream = if (shouldDecompress && encoding.exists(_.equalsIgnoreCase("gzip"))) {
384+
new GZIPInputStream(inputStream)
385+
} else if(shouldDecompress && encoding.exists(_.equalsIgnoreCase("deflate"))) {
386+
new InflaterInputStream(inputStream)
387+
} else inputStream
388+
parser(responseCode, headers, theStream)
389+
}
390+
HttpResponse[T](body, responseCode, headers)
376391
}
377-
HttpResponse[T](body, responseCode, headers)
378392
}
379393

380394
private def getResponseHeaders(conn: HttpURLConnection): Map[String, IndexedSeq[String]] = {

src/test/scala/scalaj/http/HttpBinTest.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ class HttpBinTest {
3434
assertEquals(Some("http://foo.org"), response.header("Location"))
3535
}
3636

37+
@Test
38+
def shouldFollowHttpsRedirect {
39+
val response = Http("http://httpbin.org/redirect-to?url=https://httpbin.org/get")
40+
.option(HttpOptions.followRedirects(true)).asString
41+
assertEquals(200, response.code)
42+
}
43+
3744
@Test
3845
def errorHasHeaders {
3946
val response = Http("http://httpbin.org/status/500").asString

0 commit comments

Comments
 (0)