app/com/gu/viewer/controllers/Proxy.scala (52 lines of code) (raw):

package com.gu.viewer.controllers import com.gu.pandomainauth.PanDomainAuthSettingsRefresher import com.gu.viewer.config.AppConfig import com.gu.viewer.logging.Loggable import com.gu.viewer.proxy._ import play.api.libs.ws.WSClient import play.api.mvc.{BaseController, ControllerComponents} import scala.concurrent.Future class Proxy( val controllerComponents: ControllerComponents, val wsClient: WSClient, previewProxy: PreviewProxy, liveProxy: LiveProxy, val config: AppConfig, val panDomainSettings: PanDomainAuthSettingsRefresher ) extends BaseController with Loggable with PanDomainAuthActions { private val pandaCookieName = panDomainSettings.settings.cookieSettings.cookieName def proxy(service: String, path: String) = AuthAction.async { implicit request => ProxyRequest(service, path, request) match { case r: PreviewProxyRequest => previewProxy.proxy(r.copy(maybePandaCookieToForward = request.cookies.get(pandaCookieName))) case r: LiveProxyRequest => liveProxy.proxy(r) case UnknownProxyRequest => Future.successful(BadRequest(s"Unknown proxy service: $service")) } } /** * Preview Authentication callback. * * Proxy all request params and Preview session cookie to Preview authentication callback. * Store response cookies into Viewer's play session. */ def previewAuthCallback = AuthAction.async { request => previewProxy.previewAuthCallback(PreviewProxyRequest.authCallbackRequest(request)) } /** * Redirect requests to routes that don't exist which originate (Referer header) * from a proxied request. Catches server relative requests in a proxied response. */ def redirectRelative(path: String) = AuthAction { request => val fromProxy = """^\w+:\/\/([^/]+)\/proxy\/([^/]+).*$""".r val host = request.host request.headers.get("Referer") match { case Some(fromProxy(`host`, service)) => Redirect(routes.Proxy.proxy(service, request.uri.tail)) case _ => NotFound(s"Resource not found: $path") } } /** We don't want to redirect for POST requests */ def catchRelativePost(path: String) = AuthAction.async { implicit request => val fromProxy = """^\w+:\/\/([^/]+)\/proxy\/([^/]+).*$""".r val host = request.host request.headers.get("Referer") match { case Some(fromProxy(`host`, service)) => { val body = request.body.asFormUrlEncoded ProxyRequest(service, path, request, body) match { case r: PreviewProxyRequest => previewProxy.proxyPost(r) case r: LiveProxyRequest => liveProxy.proxyPost(r) case UnknownProxyRequest => Future.successful(BadRequest(s"Unknown proxy service: $service")) } } case _ => Future.successful(NotFound(s"Resource not found: $path")) } } }