Skip to content
This repository has been archived by the owner on Dec 10, 2018. It is now read-only.

Commit

Permalink
iss #22: hedgehog.client.github.parseLinkHeader
Browse files Browse the repository at this point in the history
  • Loading branch information
maizy committed Aug 6, 2014
1 parent b715b21 commit 9094e97
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 1 deletion.
12 changes: 12 additions & 0 deletions app/hedgehog/StringUtils.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package hedgehog

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2014
* See LICENSE.txt for details.
*/
object StringUtils {
implicit class StringImplicitConverters(val string: String) {
import scala.util.control.Exception._
def toIntOpt = catching(classOf[NumberFormatException]) opt string.toInt
}
}
42 changes: 42 additions & 0 deletions app/hedgehog/clients/github/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package hedgehog.clients

import scala.util.matching.Regex
import com.netaporter.uri.Uri

import hedgehog.StringUtils.StringImplicitConverters

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2014
* See LICENSE.txt for details.
*/
package object github {

case class HeaderLink(linkType: String, link: String, page: Option[Int], perPage: Option[Int])

private val headerSplitRegexp = """,\s""".r

def parseLinkHeader(header: String): Map[String, HeaderLink] =
//ex
//<https://api.github.com/organizations/12345/repos?per_page=100&page=2>; rel="next", <https://...>; rel="last"
(for {
rel <- headerSplitRegexp.split(header)
parsed <- parseRel(rel)
} yield parsed.linkType -> parsed).toMap

private val linkRegexp = new Regex("""<([^>]+)>;\s+rel="([^"]+)"""", "link", "linkType")

def parseRel(rel: String): Option[HeaderLink] =
//ex
//<https://api.github.com/organizations/12345/repos?per_page=100&page=2>; rel="next"
(linkRegexp findFirstMatchIn rel) map {
relMatch: Regex.Match => {
val link = relMatch.group("link")
val parsedLink = Uri.parse(link)
val linkType = relMatch.group("linkType")
def paramToOptInt(paramName: String): Option[Int] = {
parsedLink.query.param(paramName).last.toIntOpt
}
HeaderLink(linkType, link, paramToOptInt("page"), paramToOptInt("per_page"))
}
}
}
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ libraryDependencies ++= Seq(
//anorm,
//cache,
"org.scalatest" % "scalatest_2.10" % "2.1.7" % "test",
"com.github.nscala-time" %% "nscala-time" % "1.2.0"
"com.github.nscala-time" %% "nscala-time" % "1.2.0",
"com.netaporter" %% "scala-uri" % "0.4.2"
)

play.Project.playScalaSettings
56 changes: 56 additions & 0 deletions test/clients/github/PackageSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package test

import org.scalatest._

import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2014
* See LICENSE.txt for details.
*/
@RunWith(classOf[JUnitRunner])
class PackageSuite extends FunSuite with Matchers {

import hedgehog.clients.github
import hedgehog.clients.github.HeaderLink

test("parseLinkHeader") {
val header =
"""<https://api.github.com/organizations/12345/repos?per_page=100&page=2>; rel="next",
|<https://api.github.com/organizations/12345/repos?per_page=100&page=5>; rel="last"""".stripMargin

assert(
github.parseLinkHeader(header) === Map(
"next" -> HeaderLink(
linkType = "next",
link = "https://api.github.com/organizations/12345/repos?per_page=100&page=2",
page = Some(2),
perPage = Some(100)
),
"last" -> HeaderLink(
linkType = "last",
link = "https://api.github.com/organizations/12345/repos?per_page=100&page=5",
page = Some(5),
perPage = Some(100)
)
)
)
}

test("parseLinkHeader for bad formatted values") {
assert(github.parseLinkHeader("") === Map())
assert(github.parseLinkHeader(", , , , ") === Map())
assert(
github.parseLinkHeader(
"""<https://api.github.com/organizations/12345/repos?per_page=100&page=2>; rel="next", bubuub"""
) === Map(
"next" -> HeaderLink(
linkType = "next",
link = "https://api.github.com/organizations/12345/repos?per_page=100&page=2",
page = Some(2),
perPage = Some(100)
)
))
}
}

0 comments on commit 9094e97

Please sign in to comment.