diff --git a/app/controllers/Application.scala b/app/controllers/Application.scala index 4bfbf0b5..8d503fba 100644 --- a/app/controllers/Application.scala +++ b/app/controllers/Application.scala @@ -73,13 +73,13 @@ class Application @Inject() ( message.toSeq.map(Html.apply) } - def index = Action.async { implicit request => + def index = Action.async { case given Request[AnyContent] => membersSummariser.fetchMembers.map { members => Ok(html.index(members, releases)) } } - def widget(version: Option[String]) = Action.async { request => + def widget(version: Option[String]) = Action.async { case given Request[AnyContent] => Future.successful( Ok(views.html.widget(news(version))), ) @@ -87,13 +87,13 @@ class Application @Inject() ( // This used to be the download/getting-started page. We are keeping // the URL for SEO purposes only. - def download = Action.async { implicit request => + def download = Action.async { case given Request[AnyContent] => Future.successful( MovedPermanently(routes.Application.gettingStarted.path), ) } - def gettingStarted = Action.async { implicit request => + def gettingStarted = Action.async { case given Request[AnyContent] => exampleProjectsService.cached() match { case Some(cached) => val examples = toExamples(cached) @@ -108,8 +108,8 @@ class Application @Inject() ( } } - def allreleases(platform: Option[String] = None) = Action.async { implicit request => - val selectedPlatform = Platform(platform.orElse(request.headers.get("User-Agent"))) + def allreleases(platform: Option[String] = None) = Action.async { case given Request[AnyContent] => + val selectedPlatform = Platform(platform.orElse(summon[Request[AnyContent]].headers.get("User-Agent"))) Future.successful( Ok(html.allreleases(releases, selectedPlatform)), ) @@ -118,9 +118,7 @@ class Application @Inject() ( def changelog = markdownAction( "public/markdown/changelog.md", - { implicit request => - views.html.changelog(_) - }, + views.html.changelog(_), ) def conduct = Action { @@ -130,17 +128,15 @@ class Application @Inject() ( def communityProcess = markdownAction( "public/markdown/community-process.md", - { implicit request => markdown => - views.html.markdownPage("Community process", markdown) - }, + markdown => views.html.markdownPage("Community process", markdown), ) def contributing = Action { Redirect("https://github.com/playframework/.github/blob/main/CONTRIBUTING.md") } - def markdownAction(markdownFile: String, template: RequestHeader => Html => Html) = Action.async { - implicit request => + def markdownAction(markdownFile: String, template: RequestHeader ?=> Html => Html) = Action.async { + case given RequestHeader => def readInputStream(is: InputStream): String = try { IOUtils.toString(is, "utf-8") @@ -166,7 +162,7 @@ class Application @Inject() ( page match { case Some(content) => Future.successful( - Ok(template(request)(Html(content))).withHeaders(CACHE_CONTROL -> "max-age=10000"), + Ok(template(Html(content))).withHeaders(CACHE_CONTROL -> "max-age=10000"), ) case None => Future.successful( @@ -175,13 +171,13 @@ class Application @Inject() ( } } - def getInvolved = Action.async { implicit request => + def getInvolved = Action.async { case given Request[AnyContent] => Future.successful( Ok(html.getInvolved()), ) } - def sponsors = Action.async { implicit request => + def sponsors = Action.async { case given Request[AnyContent] => Future.successful( Ok(html.sponsors()), ) @@ -192,7 +188,8 @@ class Application @Inject() ( MovedPermanently(url) } - def onHandlerNotFound(route: String) = Action.async { implicit request => + def onHandlerNotFound(route: String) = Action.async { case given Request[AnyContent] => + val request = summon[Request[AnyContent]] if ( route.startsWith("play-") && route.endsWith("-released") && !route .contains("-rc") && !route.contains("-m") diff --git a/app/controllers/Blog.scala b/app/controllers/Blog.scala index f7f01101..b85d0a74 100644 --- a/app/controllers/Blog.scala +++ b/app/controllers/Blog.scala @@ -28,25 +28,25 @@ class Blog @Inject() ( val blogName = "Play Framework Blog" - def index() = Action.async { implicit request => + def index() = Action.async { case given Request[AnyContent] => Future.successful( Ok(html.blog.index(blogName)), ) } - def graal() = Action.async { implicit request => + def graal() = Action.async { case given Request[AnyContent] => Future.successful( Ok(html.blog.graal(blogName, "Running Play on GraalVM")), ) } - def socketio() = Action.async { implicit request => + def socketio() = Action.async { case given Request[AnyContent] => Future.successful( Ok(html.blog.socketio(blogName, "Play socket.io support")), ) } - def ossPledgeLaunch() = Action.async { implicit request => + def ossPledgeLaunch() = Action.async { case given Request[AnyContent] => Future.successful( Ok(html.blog.ossPledgeLaunch(blogName, "Celebrating the Launch of the Open Source Pledge")), ) diff --git a/app/controllers/Code.scala b/app/controllers/Code.scala index 6a559e1c..3b513781 100644 --- a/app/controllers/Code.scala +++ b/app/controllers/Code.scala @@ -3,17 +3,19 @@ package controllers import javax.inject.Inject import play.api.mvc.AbstractController +import play.api.mvc.AnyContent import play.api.mvc.ControllerComponents +import play.api.mvc.Request import services.github.ContributorsSummariser import scala.concurrent.ExecutionContext -class Code @Inject() (contributorsSummariser: ContributorsSummariser, components: ControllerComponents)(implicit +class Code @Inject() (contributorsSummariser: ContributorsSummariser, components: ControllerComponents)(using executionContext: ExecutionContext, reverseRouter: documentation.ReverseRouter, ) extends AbstractController(components) { - def index = Action.async { implicit req => + def index = Action.async { case given Request[AnyContent] => contributorsSummariser.fetchContributors.map { contributors => Ok(views.html.code(contributors)) } diff --git a/app/controllers/Modules.scala b/app/controllers/Modules.scala index 87184e7b..e2197d53 100644 --- a/app/controllers/Modules.scala +++ b/app/controllers/Modules.scala @@ -17,7 +17,7 @@ class Modules @Inject() (modulesLookup: ModulesLookup, moduleDao: ModuleDao, com reverseRouter: documentation.ReverseRouter, ) extends AbstractController(components) { - def index(keyword: String) = Action.async { implicit request => + def index(keyword: String) = Action.async { case given Request[AnyContent] => Future.successful( render { case Accepts.Html() => @@ -29,7 +29,7 @@ class Modules @Inject() (modulesLookup: ModulesLookup, moduleDao: ModuleDao, com ) } - def download(name: String, version: String) = Action.async { implicit request => + def download(name: String, version: String) = Action.async { case given Request[AnyContent] => modulesLookup.findModule(name, version) match { case Some(zip) => Future.successful( @@ -42,20 +42,21 @@ class Modules @Inject() (modulesLookup: ModulesLookup, moduleDao: ModuleDao, com } } - def documentation(name: String, version: String, page: String) = Action.async { implicit request => - modulesLookup.loadModuleDocumentation(name, version, page) match { - case Some(content) => - Future.successful( - Ok(views.html.modules.documentation(name, content)), - ) - case None => - Future.successful( - PageNotFound, - ) - } + def documentation(name: String, version: String, page: String) = Action.async { + case given Request[AnyContent] => + modulesLookup.loadModuleDocumentation(name, version, page) match { + case Some(content) => + Future.successful( + Ok(views.html.modules.documentation(name, content)), + ) + case None => + Future.successful( + PageNotFound, + ) + } } - def show(name: String) = Action.async { implicit request => + def show(name: String) = Action.async { case given Request[AnyContent] => moduleDao.findById(name) match { case Some((module, releases)) => Future.successful( @@ -68,7 +69,7 @@ class Modules @Inject() (modulesLookup: ModulesLookup, moduleDao: ModuleDao, com } } - def dependencies(name: String, version: String) = Action.async { implicit request => + def dependencies(name: String, version: String) = Action.async { case given Request[AnyContent] => modulesLookup.findDependencies(name, version) match { case Some(yml) => Future.successful(Ok(yml)) diff --git a/app/controllers/Outreachy.scala b/app/controllers/Outreachy.scala index 8f6eda92..09afb50e 100644 --- a/app/controllers/Outreachy.scala +++ b/app/controllers/Outreachy.scala @@ -3,7 +3,9 @@ package controllers import javax.inject.Inject import play.api.mvc.AbstractController +import play.api.mvc.AnyContent import play.api.mvc.ControllerComponents +import play.api.mvc.Request import scala.concurrent.Future @@ -16,13 +18,13 @@ class Outreachy @Inject() (components: ControllerComponents)(using // def outreachy = Action(Redirect(routes.Outreachy.round15)) - def round10 = Action.async { implicit req => + def round10 = Action.async { case given Request[AnyContent] => Future.successful( Ok(views.html.outreachy.round10()), ) } - def round15 = Action.async { implicit req => + def round15 = Action.async { case given Request[AnyContent] => Future.successful( Ok(views.html.outreachy.round15()), ) diff --git a/app/controllers/Security.scala b/app/controllers/Security.scala index bfe13cfa..e1d3d697 100644 --- a/app/controllers/Security.scala +++ b/app/controllers/Security.scala @@ -3,8 +3,10 @@ package controllers import javax.inject.Inject import javax.inject.Singleton +import play.api.mvc.AnyContent import play.api.mvc.BaseController import play.api.mvc.ControllerComponents +import play.api.mvc.Request import play.api.Environment import play.twirl.api.Html import utils.Markdown @@ -13,12 +15,12 @@ import java.io.File import scala.concurrent.Future @Singleton -class Security @Inject() (environment: Environment, val controllerComponents: ControllerComponents)(implicit +class Security @Inject() (environment: Environment, val controllerComponents: ControllerComponents)(using val reverseRouter: documentation.ReverseRouter, ) extends BaseController with Common { - def vulnerability(name: String) = Action.async { implicit req => + def vulnerability(name: String) = Action.async { case given Request[AnyContent] => val path = "public/markdown/vulnerabilities/" + name // protect against dot dots @@ -51,7 +53,7 @@ class Security @Inject() (environment: Environment, val controllerComponents: Co } } - def index = Action.async { implicit req => + def index = Action.async { case given Request[AnyContent] => Future.successful( Ok(views.html.vulnerabilities()).withHeaders(CACHE_CONTROL -> "max-age=1000"), ) diff --git a/app/controllers/documentation/DocumentationController.scala b/app/controllers/documentation/DocumentationController.scala index 4508ba65..53471028 100644 --- a/app/controllers/documentation/DocumentationController.scala +++ b/app/controllers/documentation/DocumentationController.scala @@ -59,21 +59,21 @@ class DocumentationController @Inject() ( private def notModified(cacheId: String) = cacheable(NotModified, cacheId) - private def DocsAction(action: ActorRef[Command] => RequestHeader => Future[Result]) = - Action.async(parse.empty) { implicit req => - action(documentationActor)(req) + private def DocsAction(action: ActorRef[Command] => (RequestHeader ?=> Future[Result])) = + Action.async(parse.empty) { case given RequestHeader => + action(documentationActor) } private def VersionAction( version: String, - )(action: (ActorRef[Command], Version) => RequestHeader => Future[Result]) = - DocsAction { actor => implicit req => + )(action: (ActorRef[Command], Version) => (RequestHeader ?=> Future[Result])) = + DocsAction { actor => Version.parse(version).fold(Future.successful(pageNotFound(EmptyContext, "", Nil))) { v => - action(actor, v)(req) + action(actor, v) } } - private def etag(req: RequestHeader): Option[String] = { + private def etag(using req: RequestHeader): Option[String] = { req.headers.get(IF_NONE_MATCH).map { etag => if (etag.startsWith("\"") && etag.endsWith("\"")) { etag.substring(1, etag.length - 1) @@ -130,16 +130,15 @@ class DocumentationController @Inject() ( Redirect(reverseRouter.page(lang, version, "home")) } - def v1Page(lang: Option[Lang], v: String, page: String) = VersionAction(v) { - (actor, version) => implicit req => - actorRequest( - actor, - page, - (replyTo: ActorRef[Response[RenderedPage]]) => RenderV1Page(lang, version, etag(req), page, replyTo), - ) { case RenderedPage(html, _, _, _, context, cacheId) => - val result = Ok(views.html.documentation.v1(messages, context, page, html)) - cacheable(withLangHeaders(result, page, context), cacheId) - } + def v1Page(lang: Option[Lang], v: String, page: String) = VersionAction(v) { (actor, version) => + actorRequest( + actor, + page, + (replyTo: ActorRef[Response[RenderedPage]]) => RenderV1Page(lang, version, etag, page, replyTo), + ) { case RenderedPage(html, _, _, _, context, cacheId) => + val result = Ok(views.html.documentation.v1(messages, context, page, html)) + cacheable(withLangHeaders(result, page, context), cacheId) + } } def v1Image(lang: Option[Lang], v: String, image: String) = { @@ -161,19 +160,17 @@ class DocumentationController @Inject() ( ) } - def v1Cheatsheet(lang: Option[Lang], v: String, category: String) = VersionAction(v) { - (actor, version) => implicit req => - actorRequest( - actor, - category, - (replyTo: ActorRef[Response[V1Cheatsheet]]) => - RenderV1Cheatsheet(lang, version, etag(req), category, replyTo), - ) { case V1Cheatsheet(sheets, title, otherCategories, context, cacheId) => - cacheable( - Ok(views.html.documentation.cheatsheet(context, title, otherCategories, sheets)), - cacheId, - ) - } + def v1Cheatsheet(lang: Option[Lang], v: String, category: String) = VersionAction(v) { (actor, version) => + actorRequest( + actor, + category, + (replyTo: ActorRef[Response[V1Cheatsheet]]) => RenderV1Cheatsheet(lang, version, etag, category, replyTo), + ) { case V1Cheatsheet(sheets, title, otherCategories, context, cacheId) => + cacheable( + Ok(views.html.documentation.cheatsheet(context, title, otherCategories, sheets)), + cacheId, + ) + } } /** @@ -190,13 +187,13 @@ class DocumentationController @Inject() ( Redirect(reverseRouter.page(lang, version)) } - def page(lang: Option[Lang], v: String, page: String) = VersionAction(v) { (actor, version) => implicit req => + def page(lang: Option[Lang], v: String, page: String) = VersionAction(v) { (actor, version) => val linkFuture = canonicalLinkHeader(page, version) val resultFuture = actorRequest( actor, page, - (replyTo: ActorRef[Response[RenderedPage]]) => RenderPage(lang, version, etag(req), page, replyTo), + (replyTo: ActorRef[Response[RenderedPage]]) => RenderPage(lang, version, etag, page, replyTo), ) { case RenderedPage(html, sidebarHtml, breadcrumbsHtml, source, context, cacheId) => val pageTitle = HtmlHelpers.friendlyTitle(page) val result = Ok( @@ -263,7 +260,7 @@ class DocumentationController @Inject() ( * and if it matches one that we have, we redirect them to the latest for that language. * - Otherwise, we redirect them to the latest for the default language. */ - def latest(lang: Option[Lang], path: String) = DocsAction { actor => implicit req => + def latest(lang: Option[Lang], path: String) = DocsAction { actor => (actor ? GetSummary).mapTo[DocumentationSummary].map { summary => val (selectedLang, version) = lang match { // requested the default lang @@ -292,7 +289,7 @@ class DocumentationController @Inject() ( private def hasLatestDocumentation(summary: DocumentationSummary, lang: Lang): Boolean = summary.translations.contains(lang) && summary.translations(lang) == summary.defaultLatest - def sitemap = DocsAction { actor => implicit req => + def sitemap = DocsAction { actor => (actor ? GetSitemap).mapTo[DocumentationSitemap].map { docSitemap => Ok(docSitemap.sitemap.toXml) } @@ -310,8 +307,8 @@ class DocumentationController @Inject() ( message: (Version, Option[String], ActorRef[Response[Resource]]) => Command, inline: Boolean = true, ) = { - VersionAction(version) { (actor, version) => implicit req => - actor.ask[Response[Resource]](replyTo => message(version, etag(req), replyTo)).map { + VersionAction(version) { (actor, version) => + actor.ask[Response[Resource]](replyTo => message(version, etag, replyTo)).map { case DocsNotFound(context) => pageNotFound(context, resource, Nil) case DocsNotModified(cacheId) => notModified(cacheId) case Resource(source, size, cacheId) => @@ -357,11 +354,11 @@ class DocumentationController @Inject() ( ) => LangRequest[PageExists], home: String, ) = { (lang: Option[Lang], v: String, page: String) => - VersionAction(v) { (actor, version) => implicit req => + VersionAction(v) { (actor, version) => actorRequest( actor, page, - (replyTo: ActorRef[Response[PageExists]]) => msg(lang, version, etag(req), page, replyTo), + (replyTo: ActorRef[Response[PageExists]]) => msg(lang, version, etag, page, replyTo), ) { case PageExists(true, cacheId) => cacheable(TemporaryRedirect(reverseRouter.page(lang, version.name, page)), cacheId) diff --git a/test/models/documentation/DocumentationSpec.scala b/test/models/documentation/DocumentationSpec.scala index 84043818..fed43a6f 100644 --- a/test/models/documentation/DocumentationSpec.scala +++ b/test/models/documentation/DocumentationSpec.scala @@ -75,7 +75,7 @@ class DocumentationSpec extends Specification { } "display versions" should { - implicit def p(s: String): Version = Version.parse(s).get + def p(s: String): Version = Version.parse(s).get "work like this" in { mockTranslation( @@ -94,7 +94,7 @@ class DocumentationSpec extends Specification { "2.1.2", "2.1.3-RC1", ).displayVersions must containAllOf( - Seq[Version]( + Seq( "2.2-SNAPSHOT", "2.1.3-RC2", "2.1.2", @@ -103,7 +103,7 @@ class DocumentationSpec extends Specification { "2.0.4", "1.3.x", "1.2.4.1", - ), + ).map(p), ).inOrder } "should only show most recent snapshot and development version" in { @@ -114,11 +114,11 @@ class DocumentationSpec extends Specification { "2.1.4-RC1", "2.1.3", ).displayVersions must containAllOf( - Seq[Version]( + Seq( "2.2-SNAPSHOT", "2.2.0-RC1", "2.1.3", - ), + ).map(p), ).inOrder } } diff --git a/test/services/github/GitHubSpec.scala b/test/services/github/GitHubSpec.scala index 272aacd1..3a18e8f6 100644 --- a/test/services/github/GitHubSpec.scala +++ b/test/services/github/GitHubSpec.scala @@ -3,6 +3,7 @@ package services.github import play.api.http.DefaultFileMimeTypesProvider import play.api.http.DefaultFileMimeTypes import play.api.http.FileMimeTypesConfiguration +import play.api.http.Port import play.api.mvc.Results._ import play.api.routing.sird.{ GET => Get, _ } import play.api.test.PlaySpecification @@ -94,7 +95,7 @@ object GitHubSpec extends PlaySpecification { } case Get(p"/users/${_}") => components.defaultActionBuilder(Ok.sendResource("github/user.json")) } - } { implicit port => + } { case given Port => WsTestClient.withClient { ws => val gitHub = new DefaultGitHub(ws, GitHubConfig("token", "", "playframework", Nil)) block(gitHub)