| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,7 +6,7 @@ import play.api.mvc.{Action, Controller} | |||
| 6 | 6 | import common.Logging | |
| 7 | 7 | import play.api.data._ | |
| 8 | 8 | import play.api.data.Forms._ | |
| 9 | - import services.Redirects | ||
| 9 | + import services.RedirectsTemp | ||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | case class PageRedirect(from: String, to: String) { | |
@@ -24,8 +24,8 @@ class RedirectController extends Controller with Logging { | |||
| 24 | 24 | def redirectPost() = Action { implicit request => | |
| 25 | 25 | ||
| 26 | 26 | redirectForm.bindFromRequest().get.trim match { | |
| 27 | - case PageRedirect(from, "") if from.nonEmpty => Redirects.remove(from) | ||
| 28 | - case PageRedirect(from, to) if from.nonEmpty => Redirects.set(from, to) | ||
| 27 | + case PageRedirect(from, "") if from.nonEmpty => RedirectsTemp.remove(from) | ||
| 28 | + case PageRedirect(from, to) if from.nonEmpty => RedirectsTemp.set(from, to) | ||
| 29 | 29 | case _ => | |
| 30 | 30 | } | |
| 31 | 31 | ||
@@ -70,7 +70,7 @@ class RedirectController extends Controller with Logging { | |||
| 70 | 70 | val from = fromAndTo(0).trim | |
| 71 | 71 | val to = fromAndTo(1).trim | |
| 72 | 72 | try { | |
| 73 | - Redirects.set(from, to) | ||
| 73 | + RedirectsTemp.set(from, to) | ||
| 74 | 74 | s"$from -> $to" | |
| 75 | 75 | } catch { | |
| 76 | 76 | case e: Exception => s"Error processing $line: ${e.getMessage}" | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,7 +5,7 @@ import conf.Configuration | |||
| 5 | 5 | import scala.collection.JavaConversions._ | |
| 6 | 6 | import com.amazonaws.services.dynamodbv2.model.AttributeValue | |
| 7 | 7 | ||
| 8 | - object Redirects { | ||
| 8 | + object RedirectsTemp { | ||
| 9 | 9 | ||
| 10 | 10 | private lazy val table = if (Configuration.environment.isProd) "redirects" else "redirects-CODE" | |
| 11 | 11 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,8 +13,7 @@ import play.api.http.{HttpErrorHandler, HttpRequestHandler} | |||
| 13 | 13 | import play.api.mvc.EssentialFilter | |
| 14 | 14 | import play.api.routing.Router | |
| 15 | 15 | import play.api._ | |
| 16 | - import play.api.libs.ws.WSClient | ||
| 17 | - import services.{ArchiveMetrics, DynamoDB} | ||
| 16 | + import services.{ArchiveMetrics, Redirects} | ||
| 18 | 17 | import router.Routes | |
| 19 | 18 | ||
| 20 | 19 | class AppLoader extends FrontendApplicationLoader { | |
@@ -23,7 +22,7 @@ class AppLoader extends FrontendApplicationLoader { | |||
| 23 | 22 | ||
| 24 | 23 | trait AppComponents extends FrontendComponents { | |
| 25 | 24 | ||
| 26 | - lazy val dynamoDB = wire[DynamoDB] | ||
| 25 | + lazy val redirects = wire[Redirects] | ||
| 27 | 26 | ||
| 28 | 27 | lazy val healthCheck = wire[HealthCheck] | |
| 29 | 28 | lazy val archiveController = wire[ArchiveController] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,7 +4,7 @@ import campaigns.ShortCampaignCodes | |||
| 4 | 4 | import common._ | |
| 5 | 5 | import model.Cached.{CacheableResult, WithoutRevalidationResult} | |
| 6 | 6 | import play.api.mvc._ | |
| 7 | - import services.{Archive, Destination, DynamoDB, GoogleBotMetric} | ||
| 7 | + import services.{Redirects, GoogleBotMetric} | ||
| 8 | 8 | import java.net.URLDecoder | |
| 9 | 9 | import javax.ws.rs.core.UriBuilder | |
| 10 | 10 | ||
@@ -13,7 +13,7 @@ import org.apache.http.HttpStatus | |||
| 13 | 13 | ||
| 14 | 14 | import scala.concurrent.Future | |
| 15 | 15 | ||
| 16 | - class ArchiveController(dynamoDB: DynamoDB) extends Controller with Logging with ExecutionContexts { | ||
| 16 | + class ArchiveController(redirects: Redirects) extends Controller with Logging with ExecutionContexts { | ||
| 17 | 17 | ||
| 18 | 18 | private val R1ArtifactUrl = """www.theguardian.com/(.*)/[0|1]?,[\d]*,(-?\d+),[\d]*(.*)""".r | |
| 19 | 19 | private val ShortUrl = """^(www\.theguardian\.com/p/[\w\d]+).*$""".r | |
@@ -92,7 +92,7 @@ class ArchiveController(dynamoDB: DynamoDB) extends Controller with Logging with | |||
| 92 | 92 | } | |
| 93 | 93 | } | |
| 94 | 94 | ||
| 95 | - private def destinationFor(path: String): Future[Option[Destination]] = dynamoDB.destinationFor(normalise(path)) | ||
| 95 | + private def destinationFor(path: String): Future[Option[Redirects.Destination]] = redirects.destinationFor(normalise(path)) | ||
| 96 | 96 | ||
| 97 | 97 | private object Combiner { | |
| 98 | 98 | def unapply(path: String): Option[String] = { | |
@@ -142,13 +142,13 @@ class ArchiveController(dynamoDB: DynamoDB) extends Controller with Logging with | |||
| 142 | 142 | } | |
| 143 | 143 | } | |
| 144 | 144 | ||
| 145 | - private def lookupPath(path: String) = destinationFor(path).map{ _.flatMap(processLookupDestination(path).lift)} | ||
| 145 | + private def lookupPath(path: String) = destinationFor(path).map{ _.flatMap(processLookupDestination(path).lift) } | ||
| 146 | 146 | ||
| 147 | - def processLookupDestination(path: String) : PartialFunction[Destination, CacheableResult] = { | ||
| 148 | - case services.Redirect(location) if !linksToItself(path, location) => | ||
| 147 | + def processLookupDestination(path: String) : PartialFunction[Redirects.Destination, CacheableResult] = { | ||
| 148 | + case Redirects.External(location) if !linksToItself(path, location) => | ||
| 149 | 149 | val locationWithCampaign = retainShortUrlCampaign(path, location) | |
| 150 | 150 | WithoutRevalidationResult(Redirect(locationWithCampaign, redirectHttpStatus)) | |
| 151 | - case Archive(archivePath) => | ||
| 151 | + case Redirects.Archive(archivePath) => | ||
| 152 | 152 | // http://wiki.nginx.org/X-accel | |
| 153 | 153 | WithoutRevalidationResult(Ok.withHeaders("X-Accel-Redirect" -> s"/s3-archive/$archivePath")) | |
| 154 | 154 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,7 +6,7 @@ import play.api.test.Helpers._ | |||
| 6 | 6 | import org.scalatest.{BeforeAndAfterAll, DoNotDiscover, FlatSpec, Matchers} | |
| 7 | 7 | ||
| 8 | 8 | import scala.concurrent.Future | |
| 9 | - import services.DynamoDB | ||
| 9 | + import services.Redirects | ||
| 10 | 10 | ||
| 11 | 11 | @DoNotDiscover class ArchiveControllerTest | |
| 12 | 12 | extends FlatSpec | |
@@ -15,7 +15,7 @@ import services.DynamoDB | |||
| 15 | 15 | with BeforeAndAfterAll | |
| 16 | 16 | with WithTestWsClient { | |
| 17 | 17 | ||
| 18 | - lazy val archiveController = new ArchiveController(new DynamoDB(wsClient)) | ||
| 18 | + lazy val archiveController = new ArchiveController(new Redirects(wsClient)) | ||
| 19 | 19 | ||
| 20 | 20 | it should "return a normalised r1 path" in { | |
| 21 | 21 | val tests = List( | |
@@ -203,14 +203,14 @@ import services.DynamoDB | |||
| 203 | 203 | } | |
| 204 | 204 | ||
| 205 | 205 | it should "redirect short urls with campaign codes and allow for overrides" in { | |
| 206 | - val shortRedirectWithCMP = services.Redirect("http://www.theguardian.com/p/new?CMP=existing-cmp") | ||
| 206 | + val shortRedirectWithCMP = Redirects.External("http://www.theguardian.com/p/new?CMP=existing-cmp") | ||
| 207 | 207 | val result = archiveController.retainShortUrlCampaign("http://www.theguardian.com/p/old/stw", shortRedirectWithCMP.location) | |
| 208 | 208 | result should be (shortRedirectWithCMP.location) | |
| 209 | 209 | } | |
| 210 | 210 | ||
| 211 | 211 | it should "not perform a redirect loop check on Archive objects" in { | |
| 212 | 212 | // The archive x-accel goes to s3. So it is irrelevant whether the original path looks like the s3 archive path. | |
| 213 | - val databaseSaysArchive = services.Archive("http://www.theguardian.com/redirect/path-to-content") | ||
| 213 | + val databaseSaysArchive = Redirects.Archive("http://www.theguardian.com/redirect/path-to-content") | ||
| 214 | 214 | val result = archiveController.processLookupDestination("http://www.theguardian.com/redirect/path-to-content").lift(databaseSaysArchive) | |
| 215 | 215 | result.map(_.toString).getOrElse("") should include ("""X-Accel-Redirect -> /s3-archive/http://www.theguardian.com/redirect/path-to-content""") | |
| 216 | 216 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,13 +11,22 @@ import com.amazonaws.util.StringInputStream | |||
| 11 | 11 | import scala.concurrent.Future | |
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | - sealed trait Destination { | ||
| 15 | - def location: String | ||
| 14 | + object Redirects { | ||
| 15 | + sealed trait Destination { | ||
| 16 | + def location: String | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + // External refers to any non-internal redirect - that is, it could be guardian/non-guardian | ||
| 20 | + // address but will be returned in the response Location header along with 3XX status | ||
| 21 | + case class External(location: String) extends Destination | ||
| 22 | + | ||
| 23 | + // Archive refers to an internal redirect to an s3 bucket location - that is, it will | ||
| 24 | + // use the X-Accel-Redirect header to instruct nginx to perform the redirect "internally" | ||
| 25 | + case class Archive(location: String) extends Destination | ||
| 16 | 26 | } | |
| 17 | - case class Redirect(location: String) extends Destination | ||
| 18 | - case class Archive(location: String) extends Destination | ||
| 19 | 27 | ||
| 20 | - class DynamoDB(wsClient: WSClient) extends Logging with ExecutionContexts { | ||
| 28 | + | ||
| 29 | + class Redirects(wsClient: WSClient) extends Logging with ExecutionContexts { | ||
| 21 | 30 | private val tableName = if (Configuration.environment.isProd) "redirects" else "redirects-CODE" | |
| 22 | 31 | private val dynamoDbGet = "DynamoDB_20120810.GetItem" | |
| 23 | 32 | ||
@@ -26,7 +35,7 @@ class DynamoDB(wsClient: WSClient) extends Logging with ExecutionContexts { | |||
| 26 | 35 | ||
| 27 | 36 | private lazy val credentials = Configuration.aws.credentials | |
| 28 | 37 | ||
| 29 | - def destinationFor(source: String): Future[Option[Destination]] = { | ||
| 38 | + def destinationFor(source: String): Future[Option[Redirects.Destination]] = { | ||
| 30 | 39 | credentials.map{ credentialsProvider => | |
| 31 | 40 | val signer = new AWS4Signer() | |
| 32 | 41 | def signedHeaders(xAmzTarget: String, bodyContent: String) = { | |
@@ -56,8 +65,8 @@ class DynamoDB(wsClient: WSClient) extends Logging with ExecutionContexts { | |||
| 56 | 65 | .withHeaders(headers:_*) | |
| 57 | 66 | ||
| 58 | 67 | asyncRequest.post(bodyContent).map(_.json).map{ json => | |
| 59 | - (json \\ "destination").headOption.map(d => Redirect((d \ "S").as[String])) | ||
| 60 | - .orElse((json \\ "archive").headOption.map(a => Archive((a \ "S").as[String]))) | ||
| 68 | + (json \\ "destination").headOption.map(d => Redirects.External((d \ "S").as[String])) | ||
| 69 | + .orElse((json \\ "archive").headOption.map(a => Redirects.Archive((a \ "S").as[String]))) | ||
| 61 | 70 | } | |
| 62 | 71 | }.getOrElse(Future.successful(None)) | |
| 63 | 72 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments