From c73b597a06402b44f7b2364b13e2eda2612501e9 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 12 Mar 2026 18:19:10 +0000 Subject: [PATCH 1/3] Update scalafmt-core to 3.8.6 --- .scalafmt.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index ba1df7a..23cca31 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,2 +1,2 @@ -version = "3.8.1" +version = "3.8.6" runner.dialect = scala3 \ No newline at end of file From 60984603f0870296af70b937e63be9c891ea702e Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 12 Mar 2026 18:19:18 +0000 Subject: [PATCH 2/3] Reformat with scalafmt 3.8.6 Executed command: scalafmt --non-interactive --- build.sbt | 313 ++++++++++-------- .../src/main/scala/fast4s/package.scala | 6 +- .../src/main/scala/io/fast4s/api/Fast4s.scala | 170 +++++++--- .../src/main/scala/io/fast4s/api/router.scala | 5 +- .../scala/fast4s/backend/beast/package.scala | 8 +- .../backend/beast/HttpServerAsync.scala | 10 +- .../fast4s/backend/beast/HttpServerSync.scala | 13 +- .../io/fast4s/backend/beast/interop.scala | 159 +++++---- .../io/fast4s/backend/BeastStructSpec.scala | 30 +- .../main/scala/io/fast4s/common/syntax.scala | 4 +- .../scala/io/fast4s/core/HttpBuilder.scala | 34 +- .../scala/io/fast4s/core/HttpServer.scala | 36 +- .../io/fast4s/core/HttpServerBuilder.scala | 6 +- .../io/fast4s/core/HttpServerConfigs.scala | 19 +- .../scala/io/fast4s/data/ContentType.scala | 10 +- .../scala/io/fast4s/data/HttpMethod.scala | 35 +- .../scala/io/fast4s/data/HttpStatus.scala | 29 +- .../scala/io/fast4s/data/RawRequest.scala | 8 +- .../main/scala/io/fast4s/data/Request.scala | 20 +- .../main/scala/io/fast4s/data/Response.scala | 76 ++++- .../src/main/scala/io/fast4s/data/data.scala | 2 +- .../scala/io/fast4s/example/AppServer.scala | 25 +- .../scala/io/fast4s/example/ExpressLike.scala | 51 ++- .../main/scala/io/fast4s/example/main.scala | 5 +- .../main/scala/io/fast4s/example/models.scala | 7 +- .../scala/io/fast4s/example/AppServer.scala | 25 +- .../scala/io/fast4s/example/ExpressLike.scala | 51 ++- .../main/scala/io/fast4s/example/main.scala | 5 +- .../main/scala/io/fast4s/example/models.scala | 9 +- .../io/fast4s/example/ServerHandleSpec.scala | 44 ++- .../main/scala/fast4s/backend/node/node.scala | 8 +- .../fast4s/backend/node/HttpServerAsync.scala | 48 ++- .../fast4s/backend/node/HttpServerSync.scala | 7 +- 33 files changed, 735 insertions(+), 543 deletions(-) diff --git a/build.sbt b/build.sbt index b058851..158f21d 100644 --- a/build.sbt +++ b/build.sbt @@ -23,18 +23,18 @@ val sharedSettings = Seq( "-explain", "-explain-cyclic", "-source:future", - //"-Yexplicit-nulls", + // "-Yexplicit-nulls", "-Wvalue-discard", "-Wunused:all", - "-experimental", - //"-language:experimental.captureChecking", - //"-language:experimental.into", - //"-language:experimental.pureFunctions", - //"-language:experimental.modularity", - //"-language:experimental.multiSpreads", - //"-language:experimental.subCases", - //"-language:experimental.relaxedLambdaSyntax", - //"-language.experimental.separationChecking" + "-experimental" + // "-language:experimental.captureChecking", + // "-language:experimental.into", + // "-language:experimental.pureFunctions", + // "-language:experimental.modularity", + // "-language:experimental.multiSpreads", + // "-language:experimental.subCases", + // "-language:experimental.relaxedLambdaSyntax", + // "-language.experimental.separationChecking" // "-no-indent", // "-rewrite", ), @@ -50,11 +50,11 @@ lazy val appRestart = inputKey[Unit]("run app") lazy val showPid = inputKey[Unit]("show app PID") lazy val `fast4s-common` = - crossProject(JSPlatform, JVMPlatform, NativePlatform). - crossType(CrossType.Full). - in(file("fast4s-common")). - settings(sharedSettings *). - settings( + crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Full) + .in(file("fast4s-common")) + .settings(sharedSettings *) + .settings( name := "fast4s-common", organization := "io.fast4s.common", libraryDependencies ++= Seq( @@ -63,12 +63,12 @@ lazy val `fast4s-common` = ) lazy val `fast4s-data` = - crossProject(JSPlatform, JVMPlatform, NativePlatform). - crossType(CrossType.Full). - in(file("fast4s-data")). - dependsOn(`fast4s-common`). - settings(sharedSettings *). - settings( + crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Full) + .in(file("fast4s-data")) + .dependsOn(`fast4s-common`) + .settings(sharedSettings *) + .settings( name := "fast4s-data", organization := "io.fast4s.data", libraryDependencies ++= Seq( @@ -78,13 +78,13 @@ lazy val `fast4s-data` = ) lazy val `fast4s-core` = - crossProject(JSPlatform, JVMPlatform, NativePlatform). - crossType(CrossType.Full). - in(file("fast4s-core")). - dependsOn(`fast4s-common`). - dependsOn(`fast4s-data`). - settings(sharedSettings *). - settings( + crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Full) + .in(file("fast4s-core")) + .dependsOn(`fast4s-common`) + .dependsOn(`fast4s-data`) + .settings(sharedSettings *) + .settings( name := "fast4s-core", organization := "io.fast4s.core", libraryDependencies ++= Seq( @@ -94,12 +94,12 @@ lazy val `fast4s-core` = ) lazy val `fast4s-api` = - crossProject(JSPlatform, JVMPlatform, NativePlatform). - crossType(CrossType.Full). - in(file("fast4s-api")). - dependsOn(`fast4s-core`). - settings(sharedSettings *). - settings( + crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Full) + .in(file("fast4s-api")) + .dependsOn(`fast4s-core`) + .settings(sharedSettings *) + .settings( name := "fast4s-api", organization := "io.fast4s.api", libraryDependencies ++= Seq( @@ -109,26 +109,26 @@ lazy val `fast4s-api` = ) lazy val `fast4s-beast` = - crossProject(JSPlatform, JVMPlatform, NativePlatform). - crossType(CrossType.Full). - in(file("fast4s-beast")). - dependsOn(`fast4s-api`). - settings(sharedSettings *). - settings( - name := "fast4s-beast", - organization := "io.fast4s.backend.beast", - libraryDependencies ++= Seq( - "org.scalatest" %%% "scalatest" % "3.2.19" % "test" + crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Full) + .in(file("fast4s-beast")) + .dependsOn(`fast4s-api`) + .settings(sharedSettings *) + .settings( + name := "fast4s-beast", + organization := "io.fast4s.backend.beast", + libraryDependencies ++= Seq( + "org.scalatest" %%% "scalatest" % "3.2.19" % "test" + ) ) - ) lazy val `fast4s-node` = - crossProject(JSPlatform, JVMPlatform, NativePlatform). - crossType(CrossType.Full). - in(file("fast4s-node")). - dependsOn(`fast4s-api`). - settings(sharedSettings *). - settings( + crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Full) + .in(file("fast4s-node")) + .dependsOn(`fast4s-api`) + .settings(sharedSettings *) + .settings( name := "fast4s-node", organization := "io.fast4s.backend.node", libraryDependencies ++= Seq( @@ -137,33 +137,34 @@ lazy val `fast4s-node` = ) lazy val `fast4s-redis` = - crossProject(JSPlatform, JVMPlatform, NativePlatform). - crossType(CrossType.Full). - in(file("fast4s-redis")). - settings(sharedSettings *). - settings( + crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Full) + .in(file("fast4s-redis")) + .settings(sharedSettings *) + .settings( name := "fast4s-redis", organization := "io.fast4s.redis", libraryDependencies ++= Seq( "org.scalatest" %%% "scalatest" % "3.2.19" % "test" ) - ). - nativeEnablePlugins(BindgenPlugin, VcpkgNativePlugin, ScalaNativeJUnitPlugin). - nativeSettings( + ) + .nativeEnablePlugins( + BindgenPlugin, + VcpkgNativePlugin, + ScalaNativeJUnitPlugin + ) + .nativeSettings( // vcpkg vcpkgDependencies := VcpkgDependencies("hiredis"), - //vcpkgNativeConfig ~= { _.addRenamedLibrary("hiredis", "hiredis") }, + // vcpkgNativeConfig ~= { _.addRenamedLibrary("hiredis", "hiredis") }, nativeConfig ~= { c => c.withLinkingOptions(c.linkingOptions.flatMap { - case "-lresolv-lresolv" => Some("-lresolv") - case "-lm-lresolv" => None - case other => Some(other) - } ++ Seq("-lhiredis")) + case "-lresolv-lresolv" => Some("-lresolv") + case "-lm-lresolv" => None + case other => Some(other) + } ++ Seq("-lhiredis")) }, - - - bindgenBindings += { val actualIncludeFolder = new File( vcpkgConfigurator.value.pkgConfig @@ -182,13 +183,14 @@ lazy val `fast4s-redis` = .toList ) } - ). - nativeSettings(bindgenSettings). - nativeSettings(configurePlatform()) + ) + .nativeSettings(bindgenSettings) + .nativeSettings(configurePlatform()) val bindgenSettings = Seq( bindgenMode := BindgenMode.Manual( - scalaDir = (Compile / sourceDirectory).value / "scala" / "io" / "fast4s" / "hiredis", + scalaDir = + (Compile / sourceDirectory).value / "scala" / "io" / "fast4s" / "hiredis", cDir = (Compile / resourceDirectory).value / "scala-native" / "hiredis" ), bindgenBindings := { @@ -200,7 +202,9 @@ def configurePlatform(rename: String => String = identity) = Seq( nativeConfig := { val conf = nativeConfig.value val arch64 = - if (Platform.arch == Platform.Arch.Arm && Platform.bits == Platform.Bits.x64) + if ( + Platform.arch == Platform.Arch.Arm && Platform.bits == Platform.Bits.x64 + ) List("-arch", "arm64") else Nil @@ -210,85 +214,110 @@ def configurePlatform(rename: String => String = identity) = Seq( } ) - lazy val `fast4s-example` = - crossProject(JSPlatform, JVMPlatform, NativePlatform). - crossType(CrossType.Full). - in(file("fast4s-example")). - dependsOn(`fast4s-beast`). - dependsOn(`fast4s-node`). - dependsOn(`fast4s-api`). - settings(sharedSettings *). - settings( - name := "fast4s-example", - organization := "io.fast4s.example", - libraryDependencies ++= Seq( - "io.decoda" %%% "decoda" % "0.0.1", - "org.scalatest" %%% "scalatest" % "3.2.19" % "test" - ), - ). - jsSettings( - scalaJSUseMainModuleInitializer := true, - scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) } - ). - nativeSettings( - nativeConfig ~= { c => - c.withLTO(LTO.none) // thin - .withMode(Mode.debug) // releaseFast - .withGC(GC.immix) - }, - appStop := { - val logger: TaskStreams = streams.value - val shell: Seq[String] = if (sys.props("os.name").contains("Windows")) Seq("cmd", "/c") else Seq("bash", "-c") - val cmdGetPid = Seq( - "ps", "-ef", "|", "grep", name.value, "|", "grep", "-v", "grep", "|", "awk", "'{print $2}'" - ).mkString(" ") + crossProject(JSPlatform, JVMPlatform, NativePlatform) + .crossType(CrossType.Full) + .in(file("fast4s-example")) + .dependsOn(`fast4s-beast`) + .dependsOn(`fast4s-node`) + .dependsOn(`fast4s-api`) + .settings(sharedSettings *) + .settings( + name := "fast4s-example", + organization := "io.fast4s.example", + libraryDependencies ++= Seq( + "io.decoda" %%% "decoda" % "0.0.1", + "org.scalatest" %%% "scalatest" % "3.2.19" % "test" + ) + ) + .jsSettings( + scalaJSUseMainModuleInitializer := true, + scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) } + ) + .nativeSettings( + nativeConfig ~= { c => + c.withLTO(LTO.none) // thin + .withMode(Mode.debug) // releaseFast + .withGC(GC.immix) + }, + appStop := { + val logger: TaskStreams = streams.value + val shell: Seq[String] = + if (sys.props("os.name").contains("Windows")) Seq("cmd", "/c") + else Seq("bash", "-c") + val cmdGetPid = Seq( + "ps", + "-ef", + "|", + "grep", + name.value, + "|", + "grep", + "-v", + "grep", + "|", + "awk", + "'{print $2}'" + ).mkString(" ") - //logger.log.info(s"execute: ${cmdGetPid.mkString(" ")}") - val pid = ((shell :+ cmdGetPid) !!) - if (pid.nonEmpty) { + // logger.log.info(s"execute: ${cmdGetPid.mkString(" ")}") + val pid = ((shell :+ cmdGetPid) !!) + if (pid.nonEmpty) { - logger.log.info(s"PID=$pid") + logger.log.info(s"PID=$pid") - val cmd = Seq( - "kill", "-s", "9", pid - ).mkString(" ") + val cmd = Seq( + "kill", + "-s", + "9", + pid + ).mkString(" ") - val result = ((shell :+ cmd) ! logger.log) - if(result == 0){ - logger.log.success(s"stop app successful") + val result = ((shell :+ cmd) ! logger.log) + if (result == 0) { + logger.log.success(s"stop app successful") + } else { + logger.log.success("stop app failure") + } } else { - logger.log.success("stop app failure") + logger.log.info("app is not running") } - } else { - logger.log.info("app is not running") - } - }, - - showPid := { - val logger: TaskStreams = streams.value - val shell: Seq[String] = if (sys.props("os.name").contains("Windows")) Seq("cmd", "/c") else Seq("bash", "-c") - val cmd = Seq( - "ps", "-ef", "|", "grep", name.value, "|", "grep", "-v", "grep", "|", "awk", "'{print $2}'" - ).mkString(" ") + }, + showPid := { + val logger: TaskStreams = streams.value + val shell: Seq[String] = + if (sys.props("os.name").contains("Windows")) Seq("cmd", "/c") + else Seq("bash", "-c") + val cmd = Seq( + "ps", + "-ef", + "|", + "grep", + name.value, + "|", + "grep", + "-v", + "grep", + "|", + "awk", + "'{print $2}'" + ).mkString(" ") - //logger.log.info(s"execute: ${cmd.mkString(" ")}") - val pid = (shell :+ cmd) !! + // logger.log.info(s"execute: ${cmd.mkString(" ")}") + val pid = (shell :+ cmd) !! - if(pid.nonEmpty){ - logger.log.info(s"PID=$pid") - }else{ - logger.log.info(s"pid not found") + if (pid.nonEmpty) { + logger.log.info(s"PID=$pid") + } else { + logger.log.info(s"pid not found") + } + }, + appRestart := { + val logger: TaskStreams = streams.value + logger.log.info("app restart..") + appStop.evaluated + (Compile / run).evaluated } - }, - appRestart := { - val logger: TaskStreams = streams.value - logger.log.info("app restart..") - appStop.evaluated - (Compile / run).evaluated - } - ) - + ) addCommandAlias("run", "app/appStart") - diff --git a/fast4s-api/shared/src/main/scala/fast4s/package.scala b/fast4s-api/shared/src/main/scala/fast4s/package.scala index 57ecd6c..ace9390 100644 --- a/fast4s-api/shared/src/main/scala/fast4s/package.scala +++ b/fast4s-api/shared/src/main/scala/fast4s/package.scala @@ -31,9 +31,9 @@ package object fast4s: Put, Delete, Trace, - Connect, + Connect } - + export io.fast4s.api.Fast4s export io.fast4s.api.Fast4s.fast @@ -44,4 +44,4 @@ package object fast4s: Controller, Handler, Dispatcher - } \ No newline at end of file + } diff --git a/fast4s-api/shared/src/main/scala/io/fast4s/api/Fast4s.scala b/fast4s-api/shared/src/main/scala/io/fast4s/api/Fast4s.scala index f9e0766..30e258b 100644 --- a/fast4s-api/shared/src/main/scala/io/fast4s/api/Fast4s.scala +++ b/fast4s-api/shared/src/main/scala/io/fast4s/api/Fast4s.scala @@ -8,7 +8,7 @@ import scala.collection.mutable object Fast4s: - //private type ServerResult = RequestBuilder[Request, RawRequest] ?=> Int + // private type ServerResult = RequestBuilder[Request, RawRequest] ?=> Int private val _routes = mutable.ListBuffer[RouteEntry[Request, Response]]() @@ -25,11 +25,12 @@ object Fast4s: _routes.addOne(route) route - - private def buildServer(host: String, - port: Int, - workers: Int, - routes: Seq[RouteEntry[Request, Response]])(using creator: HttpServerCreator): HttpServer = + private def buildServer( + host: String, + port: Int, + workers: Int, + routes: Seq[RouteEntry[Request, Response]] + )(using creator: HttpServerCreator): HttpServer = val cfg = HttpServerConfigs( host = host, port = port, @@ -38,100 +39,164 @@ object Fast4s: recover = _recover, interceptors = _interceptors.toMap, leave = _leave.toSeq, - enter = _enter.toSeq, + enter = _enter.toSeq ) creator(cfg).build - private def runServer(host: String, - port: Int, - workers: Int, - routes: Seq[RouteEntry[Request, Response]])(using creator: HttpServerCreator): Int = + private def runServer( + host: String, + port: Int, + workers: Int, + routes: Seq[RouteEntry[Request, Response]] + )(using creator: HttpServerCreator): Int = buildServer(host, port, workers, routes).serve - object fast: - //import io.fast4s.core.requestBuilder + // import io.fast4s.core.requestBuilder - def get(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def get( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(GET, path, c) |> register - def get(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def get(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(GET, path)(f) |> register - def get(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def get(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(GET, path)(f) |> register - def head(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def head( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(HEAD, path, c) |> register - def head(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def head(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(HEAD, path)(f) |> register - def head(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def head(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(HEAD, path)(f) |> register - def options(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def options( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(OPTIONS, path, c) |> register - def options(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def options(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(OPTIONS, path)(f) |> register - def options(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def options(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(OPTIONS, path)(f) |> register - def post(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def post( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(POST, path, c) |> register - def post(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def post(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(POST, path)(f) |> register - def post(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def post(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(POST, path)(f) |> register - def put(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def put( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(PUT, path, c) |> register - def put(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def put(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(PUT, path)(f) |> register - def put(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def put(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(PUT, path)(f) |> register - def delete(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def delete( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(DELETE, path, c) |> register - def delete(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def delete(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(DELETE, path)(f) |> register - def delete(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def delete(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(DELETE, path)(f) |> register - def patch(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def patch( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(PATCH, path, c) |> register - def patch(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def patch(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(PATCH, path)(f) |> register - def patch(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def patch(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(PATCH, path)(f) |> register - def connect(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def connect( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(CONNECT, path, c) |> register - def connect(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def connect(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(CONNECT, path)(f) |> register - def connect(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def connect(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(CONNECT, path)(f) |> register - def any(path: String, c: Controller[Request, Response]): RouteEntry[Request, Response] = + def any( + path: String, + c: Controller[Request, Response] + ): RouteEntry[Request, Response] = route(ANY, path, c) |> register - def any(path: String)(f: HttpHandler[Request, Response]): RouteEntry[Request, Response] = + def any(path: String)( + f: HttpHandler[Request, Response] + ): RouteEntry[Request, Response] = route(ANY, path)(f) |> register - def any(path: String)(f: Dispatcher[Request, Response]): RouteEntry[Request, Response] = + def any(path: String)( + f: Dispatcher[Request, Response] + ): RouteEntry[Request, Response] = route(ANY, path)(f) |> register def routes(items: RouteEntry[Request, Response]*): Unit = @@ -144,22 +209,37 @@ object Fast4s: def intercept(status: Int)(f: Interceptor): Unit = _interceptors.addOne(status -> f) - def enter(method: HttpMethod, path: String)(f: MiddlewareEnter[Request, Response]): Unit = + def enter(method: HttpMethod, path: String)( + f: MiddlewareEnter[Request, Response] + ): Unit = ns(path, Enter(method.toMethod :: Nil, f)) - def leave(method: HttpMethod, path: String)(f: MiddlewareLeave[Request, Response]): Unit = + def leave(method: HttpMethod, path: String)( + f: MiddlewareLeave[Request, Response] + ): Unit = ns(path, Leave(method.toMethod :: Nil, f)) - def ns(path: String, m: Leave[Request, Response] | Enter[Request, Response]): Unit = + def ns( + path: String, + m: Leave[Request, Response] | Enter[Request, Response] + ): Unit = m match case leave: Leave[Request, Response] => _leave.addOne((path, leave)) case enter: Enter[Request, Response] => _enter.addOne((path, enter)) - def serve(hostname: String = "0.0.0.0", port: Int = 3000, workers: Int = 1): HttpServerCreator ?=> Int = + def serve( + hostname: String = "0.0.0.0", + port: Int = 3000, + workers: Int = 1 + ): HttpServerCreator ?=> Int = runServer(hostname, port, workers, _routes.toSeq) object server: - def create(hostname: String = "0.0.0.0", port: Int = 3000, workers: Int = 1): HttpServerCreator ?=> HttpServer = + def create( + hostname: String = "0.0.0.0", + port: Int = 3000, + workers: Int = 1 + ): HttpServerCreator ?=> HttpServer = Fast4s.buildServer(hostname, port, workers, _routes.toSeq) diff --git a/fast4s-api/shared/src/main/scala/io/fast4s/api/router.scala b/fast4s-api/shared/src/main/scala/io/fast4s/api/router.scala index e9953d4..5de820e 100644 --- a/fast4s-api/shared/src/main/scala/io/fast4s/api/router.scala +++ b/fast4s-api/shared/src/main/scala/io/fast4s/api/router.scala @@ -10,6 +10,5 @@ object router: type Controller = types.Controller[Request, Response] type Handler = types.HttpHandler[Request, Response] type Dispatcher = types.Dispatcher[Request, Response] - //type MiddlewareEnter = types.MiddlewareEnter[Request, Response] - //type MiddlewareLeave = types.MiddlewareLeave[Request, Response] - + // type MiddlewareEnter = types.MiddlewareEnter[Request, Response] + // type MiddlewareLeave = types.MiddlewareLeave[Request, Response] diff --git a/fast4s-beast/native/src/main/scala/fast4s/backend/beast/package.scala b/fast4s-beast/native/src/main/scala/fast4s/backend/beast/package.scala index 9c0591f..f1f9678 100644 --- a/fast4s-beast/native/src/main/scala/fast4s/backend/beast/package.scala +++ b/fast4s-beast/native/src/main/scala/fast4s/backend/beast/package.scala @@ -5,8 +5,8 @@ import io.fast4s.core.{HttpServerConfigs, HttpServerCreator, requestBuilder} package object beast: - given sync: HttpServerCreator = - (cfg: HttpServerConfigs) => HttpServerSync(cfg) + given sync: HttpServerCreator = + (cfg: HttpServerConfigs) => HttpServerSync(cfg) - given async: HttpServerCreator = - (cfg: HttpServerConfigs) => HttpServerAsync(cfg) + given async: HttpServerCreator = + (cfg: HttpServerConfigs) => HttpServerAsync(cfg) diff --git a/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/HttpServerAsync.scala b/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/HttpServerAsync.scala index 009be22..c2a804f 100644 --- a/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/HttpServerAsync.scala +++ b/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/HttpServerAsync.scala @@ -31,11 +31,8 @@ object HttpServerAsync: beastCallback(req, resp.ptr()) } - - -trait HttpServerAsync(val host: String, - val port: Int, - val workers: Int = 1) extends HttpServer: +trait HttpServerAsync(val host: String, val port: Int, val workers: Int = 1) + extends HttpServer: override def run: Int = Zone: @@ -44,4 +41,5 @@ trait HttpServerAsync(val host: String, port.toUShort, workers.toUShort, CFuncPtr3.fromScalaFunction(threadStart), - CFuncPtr2.fromScalaFunction(HttpServerAsync.handle)) + CFuncPtr2.fromScalaFunction(HttpServerAsync.handle) + ) diff --git a/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/HttpServerSync.scala b/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/HttpServerSync.scala index 45ce607..dc1b9ec 100644 --- a/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/HttpServerSync.scala +++ b/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/HttpServerSync.scala @@ -10,12 +10,11 @@ import scala.scalanative.unsafe import scala.scalanative.unsafe.{CFuncPtr1, CFuncPtr3, Ptr, Zone} import scala.scalanative.unsigned.UnsignedRichInt - object HttpServerSync: def apply(cfg: HttpServerConfigs): Fast4sRequestBuilder ?=> HttpServerSync = new HttpServerSync(cfg.host, cfg.port, cfg.workers) { - def router: Router[Request, Response, RawRequest] = Router(cfg.routes *) + def router: Router[Request, Response, RawRequest] = Router(cfg.routes*) def recover: Option[Recover] = cfg.recover @@ -26,17 +25,14 @@ object HttpServerSync: def enter: Seq[NSEnter] = cfg.enter } - private def handle(req: Ptr[BeastRequest]): Ptr[BeastResponse] = { val resp = HttpServer.handle(req.request()) Zone: resp.ptr() } - -trait HttpServerSync(val host: String, - val port: Int, - val workers: Int = 1) extends HttpServer: +trait HttpServerSync(val host: String, val port: Int, val workers: Int = 1) + extends HttpServer: override def run: Int = Zone: @@ -45,4 +41,5 @@ trait HttpServerSync(val host: String, port.toUShort, workers.toUShort, CFuncPtr3.fromScalaFunction(threadStart), - CFuncPtr1.fromScalaFunction(HttpServerSync.handle)) \ No newline at end of file + CFuncPtr1.fromScalaFunction(HttpServerSync.handle) + ) diff --git a/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/interop.scala b/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/interop.scala index 018cdd0..149b704 100644 --- a/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/interop.scala +++ b/fast4s-beast/native/src/main/scala/io/fast4s/backend/beast/interop.scala @@ -5,8 +5,6 @@ import io.fast4s.data.* import scala.collection.{immutable, mutable} import scala.scalanative.unsafe.* - - object Structs: import Util.* @@ -33,11 +31,14 @@ object Structs: // header start pointer, size type BeastHeaders = CStruct2[Ptr[BeastHeader], CInt] object BeastHeaders: - given _tag: Tag[BeastHeaders] = Tag.materializeCStruct2Tag[Ptr[BeastHeader], CInt] + given _tag: Tag[BeastHeaders] = + Tag.materializeCStruct2Tag[Ptr[BeastHeader], CInt] def apply()(using Zone): Ptr[BeastHeaders] = alloc[BeastHeaders](1) - def apply(header: Ptr[BeastHeader], size: CInt)(using Zone): Ptr[BeastHeaders] = + def apply(header: Ptr[BeastHeader], size: CInt)(using + Zone + ): Ptr[BeastHeaders] = val ___ptr = apply() (!___ptr).header = header (!___ptr).size = size @@ -75,31 +76,35 @@ object Structs: // body {str, body raw, int} type BeastBody = CStruct3[CString, Ptr[Byte], CInt] object BeastBody: - given _tag: Tag[BeastBody] = Tag.materializeCStruct3Tag[CString, Ptr[Byte], CInt] + given _tag: Tag[BeastBody] = + Tag.materializeCStruct3Tag[CString, Ptr[Byte], CInt] def apply()(using Zone): Ptr[BeastBody] = alloc[BeastBody](1) - def apply(body: CString, buff: Ptr[Byte], size: CInt)(using Zone): Ptr[BeastBody] = + def apply(body: CString, buff: Ptr[Byte], size: CInt)(using + Zone + ): Ptr[BeastBody] = val ___ptr = apply() (!___ptr)._body = body (!___ptr)._buff = buff (!___ptr)._size = size ___ptr - def apply(body: Option[String], rawBody: Option[immutable.Seq[Byte]])(using Zone): Ptr[BeastBody] = + def apply(body: Option[String], rawBody: Option[immutable.Seq[Byte]])(using + Zone + ): Ptr[BeastBody] = val size = rawBody.map(_.length).getOrElse(0) val rawBodyPtr = if size == 0 - then null.asInstanceOf[Ptr[Byte]] + then null.asInstanceOf[Ptr[Byte]] else val buff = rawBody.get val raw = alloc[Byte](size) - for i <- 0 until size do - raw(i) = buff(i) + for i <- 0 until size do raw(i) = buff(i) raw val bodyPtr = body.map(_.c_str).orNull match - case null => null.asInstanceOf[Ptr[Byte]] - case s: CString => s + case null => null.asInstanceOf[Ptr[Byte]] + case s: CString => s EasyBeast.newBody(bodyPtr, rawBodyPtr, size) extension (struct: BeastBody) @@ -126,19 +131,27 @@ object Structs: val ptr = struct._buff val len = struct._size val buff = mutable.ArrayBuilder.ofByte() - for i <- 0 until len do - buff.addOne(ptr(i)) + for i <- 0 until len do buff.addOne(ptr(i)) Some(buff.result().toSeq) - // verb, target, content type, {body str, body bytes, size} , {[{name, value], size} - type BeastRequest = CStruct5[CString, CString, CString, Ptr[BeastBody], Ptr[BeastHeaders]] + type BeastRequest = + CStruct5[CString, CString, CString, Ptr[BeastBody], Ptr[BeastHeaders]] object BeastRequest: - given _tag: Tag[BeastRequest] = Tag.materializeCStruct5Tag[CString, CString, CString, Ptr[BeastBody], Ptr[BeastHeaders]] + given _tag: Tag[BeastRequest] = + Tag.materializeCStruct5Tag[CString, CString, CString, Ptr[BeastBody], Ptr[ + BeastHeaders + ]] def apply()(using Zone): Ptr[BeastRequest] = alloc[BeastRequest](1) - def apply(method: CString, target: CString, contentType: CString, body: Ptr[BeastBody], headers: Ptr[BeastHeaders])(using Zone): Ptr[BeastRequest] = + def apply( + method: CString, + target: CString, + contentType: CString, + body: Ptr[BeastBody], + headers: Ptr[BeastHeaders] + )(using Zone): Ptr[BeastRequest] = val ___ptr = apply() (!___ptr)._method = method (!___ptr)._target = target @@ -170,24 +183,28 @@ object Structs: def body: Option[String] = if struct._body == null then None - else - (!struct._body).body + else (!struct._body).body def rawBody: Option[immutable.Seq[Byte]] = if struct._body == null then None - else - (!struct._body).rawBody - + else (!struct._body).rawBody // status {code, content type, {body str, body bytes, size}, {[{name, value], size}} - type BeastResponse = CStruct4[CInt, CString, Ptr[BeastBody], Ptr[BeastHeaders]] + type BeastResponse = + CStruct4[CInt, CString, Ptr[BeastBody], Ptr[BeastHeaders]] object BeastResponse: - given _tag: Tag[BeastResponse] = Tag.materializeCStruct4Tag[CInt, CString, Ptr[BeastBody], Ptr[BeastHeaders]] + given _tag: Tag[BeastResponse] = Tag + .materializeCStruct4Tag[CInt, CString, Ptr[BeastBody], Ptr[BeastHeaders]] def apply()(using Zone): Ptr[BeastResponse] = alloc[BeastResponse](1) - def apply(status: CInt, contentType: CString, body: Ptr[BeastBody], headers: Ptr[BeastHeaders])(using Zone): Ptr[BeastResponse] = + def apply( + status: CInt, + contentType: CString, + body: Ptr[BeastBody], + headers: Ptr[BeastHeaders] + )(using Zone): Ptr[BeastResponse] = val ___ptr = apply() (!___ptr).status = status (!___ptr)._contentType = contentType @@ -195,9 +212,15 @@ object Structs: (!___ptr)._headers = headers ___ptr - def apply(status: Int, contentType: String, body: Option[String], rawBody: Option[immutable.Seq[Byte]], headers: Map[String, String])(using Zone): Ptr[BeastResponse] = + def apply( + status: Int, + contentType: String, + body: Option[String], + rawBody: Option[immutable.Seq[Byte]], + headers: Map[String, String] + )(using Zone): Ptr[BeastResponse] = val resp = EasyBeast.newResponse(status) - (!resp)._contentType = contentType.c_str + (!resp)._contentType = contentType.c_str (!resp)._body = BeastBody(body, rawBody) (!resp)._headers = BeastHeaders(headers) resp @@ -229,34 +252,36 @@ object Structs: then None else (!struct._body).rawBody - - type BeastHandlerCallback = CFuncPtr2[Ptr[BeastRequest], Ptr[BeastResponse], Unit] + type BeastHandlerCallback = + CFuncPtr2[Ptr[BeastRequest], Ptr[BeastResponse], Unit] type BeastHttpHandlerSync = CFuncPtr1[Ptr[BeastRequest], Ptr[BeastResponse]] - type BeastHttpHandlerAsync = CFuncPtr2[Ptr[BeastRequest], BeastHandlerCallback, Unit] + type BeastHttpHandlerAsync = + CFuncPtr2[Ptr[BeastRequest], BeastHandlerCallback, Unit] type ThreadInit = CFuncPtr1[Ptr[Byte], Unit] type ThreadStarter = CFuncPtr3[ThreadInit, CInt, Ptr[Byte], Unit] object Util: - extension (cs: CString) - def str: String = fromCString(cs) + extension (cs: CString) def str: String = fromCString(cs) extension (s: String)(using Zone) def c_str: CString = toCString(s) - def threadStart(init: Structs.ThreadInit, workers: CInt, ptr: Ptr[Byte]): Unit = + def threadStart( + init: Structs.ThreadInit, + workers: CInt, + ptr: Ptr[Byte] + ): Unit = val threads = - for _ <- 0 until workers yield - new Thread: - override def run(): Unit = - init(ptr) + for _ <- 0 until workers + yield new Thread: + override def run(): Unit = + init(ptr) - for t <- threads do - t.start() + for t <- threads do t.start() - for t <- threads do - t.join() + for t <- threads do t.join() object Ext: import Structs.*, Util.* @@ -268,9 +293,10 @@ object Ext: method = HttpMethod(req.method), target = req.target, body = req.body.getOrElse(""), - contentType = req.contentType.map(ContentType.make).getOrElse(ContentType.Empty), + contentType = + req.contentType.map(ContentType.make).getOrElse(ContentType.Empty), bodyRaw = req.rawBody.getOrElse(Nil), - headers = req.headers, + headers = req.headers ) extension (respPtr: Ptr[BeastResponse]) @@ -281,7 +307,7 @@ object Ext: contentType = ContentType.make(resp.contentType.getOrElse("")), body = resp.body.getOrElse(""), rawBody = resp.rawBody.getOrElse(Nil), - headers = resp.headers, + headers = resp.headers ) extension (req: Request)(using Zone) @@ -292,9 +318,10 @@ object Ext: req.contentType.mimeType.c_str, BeastBody( Option.when(req.body.nonEmpty)(req.body), - Option.when(req.bodyRaw.nonEmpty)(req.bodyRaw)), - BeastHeaders(req.headers)) - + Option.when(req.bodyRaw.nonEmpty)(req.bodyRaw) + ), + BeastHeaders(req.headers) + ) extension (resp: Response) def ptr()(using Zone): Ptr[BeastResponse] = @@ -303,7 +330,8 @@ object Ext: contentType = resp.contentType.mimeType, body = Option.when(resp.body.nonEmpty)(resp.body), rawBody = Option.when(resp.rawBody.nonEmpty)(resp.rawBody), - headers = resp.headers) + headers = resp.headers + ) @linkCppRuntime @link("EasyBeast") @@ -311,25 +339,32 @@ object Ext: object EasyBeast: @name("run_sync") - def runSync(hostname: CString, - port: CUnsignedShort, - maxThread: CUnsignedShort, - threadStarter: Structs.ThreadStarter, - handler: Structs.BeastHttpHandlerSync): CInt = extern + def runSync( + hostname: CString, + port: CUnsignedShort, + maxThread: CUnsignedShort, + threadStarter: Structs.ThreadStarter, + handler: Structs.BeastHttpHandlerSync + ): CInt = extern @name("run_async") - def runAsync(hostname: CString, - port: CUnsignedShort, - maxThread: CUnsignedShort, - threadStarter: Structs.ThreadStarter, - handler: CFuncPtr): CInt = extern - + def runAsync( + hostname: CString, + port: CUnsignedShort, + maxThread: CUnsignedShort, + threadStarter: Structs.ThreadStarter, + handler: CFuncPtr + ): CInt = extern @name("response_new") def newResponse(statusCode: CInt): Ptr[Structs.BeastResponse] = extern @name("body_new") - def newBody(body: CString, rawBody: Ptr[Byte], size: CInt): Ptr[Structs.BeastBody] = extern + def newBody( + body: CString, + rawBody: Ptr[Byte], + size: CInt + ): Ptr[Structs.BeastBody] = extern @name("headers_new") - def newHeaders(size: CInt): Ptr[Structs.BeastHeaders] = extern \ No newline at end of file + def newHeaders(size: CInt): Ptr[Structs.BeastHeaders] = extern diff --git a/fast4s-beast/native/src/test/scala/io/fast4s/backend/BeastStructSpec.scala b/fast4s-beast/native/src/test/scala/io/fast4s/backend/BeastStructSpec.scala index b5813c7..f8244a5 100644 --- a/fast4s-beast/native/src/test/scala/io/fast4s/backend/BeastStructSpec.scala +++ b/fast4s-beast/native/src/test/scala/io/fast4s/backend/BeastStructSpec.scala @@ -10,14 +10,18 @@ import scala.scalanative.unsafe.Zone class BeastStructSpec extends AnyFunSuite with Matchers: - test("struct converter test"){ + test("struct converter test") { Zone: val req = Request( method = HttpMethod.Get, target = "/", body = "request!", - headers = Map("Content-Type" -> "application/json; charset=UTF-8", "Accept-Encoding" -> "gzip", "Accept-Language" -> "en-US,es;q=0.5"), + headers = Map( + "Content-Type" -> "application/json; charset=UTF-8", + "Accept-Encoding" -> "gzip", + "Accept-Language" -> "en-US,es;q=0.5" + ) ) val reqPtr = req.ptr() @@ -27,7 +31,11 @@ class BeastStructSpec extends AnyFunSuite with Matchers: val resp = Response( status = HttpStatus.OK, body = "response!!", - headers = Map("Content-Type" -> "application/json; charset=UTF-8", "Accept-Encoding" -> "gzip", "Accept-Language" -> "en-US,es;q=0.5") + headers = Map( + "Content-Type" -> "application/json; charset=UTF-8", + "Accept-Encoding" -> "gzip", + "Accept-Language" -> "en-US,es;q=0.5" + ) ) val respPtr = resp.ptr() @@ -42,7 +50,11 @@ class BeastStructSpec extends AnyFunSuite with Matchers: method = HttpMethod.Get, target = "/", bodyRaw = Seq('A', 'B', 'C', 'D'), - headers = Map("Content-Type" -> "application/json; charset=UTF-8", "Accept-Encoding" -> "gzip", "Accept-Language" -> "en-US,es;q=0.5"), + headers = Map( + "Content-Type" -> "application/json; charset=UTF-8", + "Accept-Encoding" -> "gzip", + "Accept-Language" -> "en-US,es;q=0.5" + ) ) val reqPtr = req.ptr() @@ -53,7 +65,11 @@ class BeastStructSpec extends AnyFunSuite with Matchers: val resp = Response( status = HttpStatus.OK, rawBody = Seq('A', 'B', 'C', 'D'), - headers = Map("Content-Type" -> "application/json; charset=UTF-8", "Accept-Encoding" -> "gzip", "Accept-Language" -> "en-US,es;q=0.5") + headers = Map( + "Content-Type" -> "application/json; charset=UTF-8", + "Accept-Encoding" -> "gzip", + "Accept-Language" -> "en-US,es;q=0.5" + ) ) val respPtr = resp.ptr() @@ -61,7 +77,3 @@ class BeastStructSpec extends AnyFunSuite with Matchers: respOther `shouldBe` resp } - - - - diff --git a/fast4s-common/native/src/main/scala/io/fast4s/common/syntax.scala b/fast4s-common/native/src/main/scala/io/fast4s/common/syntax.scala index 76b2f94..eaf52d0 100644 --- a/fast4s-common/native/src/main/scala/io/fast4s/common/syntax.scala +++ b/fast4s-common/native/src/main/scala/io/fast4s/common/syntax.scala @@ -3,10 +3,8 @@ package io.fast4s.common import scala.scalanative.unsafe.* object syntax: - extension (cs: CString) - def str: String = fromCString(cs) + extension (cs: CString) def str: String = fromCString(cs) extension (s: String)(using Zone) def c_str: CString = toCString(s) - diff --git a/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpBuilder.scala b/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpBuilder.scala index d0981d7..ab615c7 100644 --- a/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpBuilder.scala +++ b/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpBuilder.scala @@ -8,21 +8,21 @@ type Fast4sRequestBuilder = RequestBuilder[Request, RawRequest] given requestBuilder: Fast4sRequestBuilder = (routeInfo: RouteInfo, rawReq: Option[RawRequest]) => - val headers = rawReq.map(_.headers).getOrElse(Map()) - val contentType = headers - .find(_._1.toLowerCase == "content-type") - .map(_._2) - .map(ContentType.make) - .getOrElse(ContentType.Empty) + val headers = rawReq.map(_.headers).getOrElse(Map()) + val contentType = headers + .find(_._1.toLowerCase == "content-type") + .map(_._2) + .map(ContentType.make) + .getOrElse(ContentType.Empty) - Request( - routeInfo.method.toHttpMethod, - routeInfo.target, - rawReq.map(_.body).getOrElse(""), - contentType, - rawReq.map(_.bodyRaw).getOrElse(Nil), - headers, - routeInfo.params, - routeInfo.query, - routeInfo.matcher - ) \ No newline at end of file + Request( + routeInfo.method.toHttpMethod, + routeInfo.target, + rawReq.map(_.body).getOrElse(""), + contentType, + rawReq.map(_.bodyRaw).getOrElse(Nil), + headers, + routeInfo.params, + routeInfo.query, + routeInfo.matcher + ) diff --git a/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServer.scala b/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServer.scala index f06c2df..0b52c73 100644 --- a/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServer.scala +++ b/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServer.scala @@ -64,12 +64,14 @@ private[fast4s] object HttpServer: else resp each(res, xs) each(response, server.leave) - */ - private inline def applyInterceptors(request: Request)(response: Response): Response = + */ + private inline def applyInterceptors(request: Request)( + response: Response + ): Response = @tailrec def each(resp: Response, items: Seq[Interceptor]): Response = items match - case Nil => resp + case Nil => resp case x :: xs => each(x.apply(request, resp), xs) val its = server.interceptors .filter(_._1 == response.status.code) @@ -78,22 +80,21 @@ private[fast4s] object HttpServer: each(response, its) inline def handle(request: Request): Response = - try { - /* + try { + /* val resp = applyEnter(request) match case r: Request => dispatch(r) case r: Response => r applyLeave(request, resp) |> applyInterceptors(request) - */ - dispatch(request) |> applyInterceptors(request) - } catch - case err: Throwable => - println("Error during http server handle: " + err) - server - .recover - .map(f => f(request, err)) - .getOrElse(Response.serverError()) + */ + dispatch(request) |> applyInterceptors(request) + } catch + case err: Throwable => + println("Error during http server handle: " + err) + server.recover + .map(f => f(request, err)) + .getOrElse(Response.serverError()) inline def dispatch(request: Request): Response = val target = request.target @@ -104,8 +105,7 @@ private[fast4s] object HttpServer: request.headers ) - server - .router + server.router .dispatch(method, target, extra) match - case Some(resp) => resp - case _ => Response.notFound("Not Found") \ No newline at end of file + case Some(resp) => resp + case _ => Response.notFound("Not Found") diff --git a/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServerBuilder.scala b/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServerBuilder.scala index d6011f0..327a5e8 100644 --- a/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServerBuilder.scala +++ b/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServerBuilder.scala @@ -33,7 +33,9 @@ class HttpServerBuilder: cfg = cfg.copy(recover = Some(recover)) this - def withInterceptor(status: Int)(interceptor: => Interceptor): HttpServerBuilder = + def withInterceptor(status: Int)( + interceptor: => Interceptor + ): HttpServerBuilder = cfg = cfg.copy(interceptors = cfg.interceptors + (status -> interceptor)) this @@ -62,4 +64,4 @@ class HttpServerBuilder: object HttpServerBuilder: - def apply(): HttpServerBuilder = new HttpServerBuilder() \ No newline at end of file + def apply(): HttpServerBuilder = new HttpServerBuilder() diff --git a/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServerConfigs.scala b/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServerConfigs.scala index db8480c..c6695e2 100644 --- a/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServerConfigs.scala +++ b/fast4s-core/shared/src/main/scala/io/fast4s/core/HttpServerConfigs.scala @@ -3,13 +3,14 @@ package io.fast4s.core import io.fast4s.data.{Request, Response} import via.types.* -case class HttpServerConfigs(host: String = "0.0.0.0", - port: Int = 3000, - workers: Int = 1, - routes: Seq[RouteEntry[Request, Response]] = Nil, - recover: Option[Recover] = None, - interceptors: Map[Int, Interceptor] = Map(), - leave: Seq[NSLeave] = Nil, - enter: Seq[NSEnter] = Nil, - async: Boolean = false +case class HttpServerConfigs( + host: String = "0.0.0.0", + port: Int = 3000, + workers: Int = 1, + routes: Seq[RouteEntry[Request, Response]] = Nil, + recover: Option[Recover] = None, + interceptors: Map[Int, Interceptor] = Map(), + leave: Seq[NSLeave] = Nil, + enter: Seq[NSEnter] = Nil, + async: Boolean = false ) diff --git a/fast4s-data/shared/src/main/scala/io/fast4s/data/ContentType.scala b/fast4s-data/shared/src/main/scala/io/fast4s/data/ContentType.scala index c6f7f64..2ff31b2 100644 --- a/fast4s-data/shared/src/main/scala/io/fast4s/data/ContentType.scala +++ b/fast4s-data/shared/src/main/scala/io/fast4s/data/ContentType.scala @@ -18,9 +18,15 @@ object ContentType: def make(text: String): ContentType = val options = List( - Json, JavaScript, Html, Text, CSS, PNG, JPG, JPEG + Json, + JavaScript, + Html, + Text, + CSS, + PNG, + JPG, + JPEG ) options .find(_.mimeType == text) .getOrElse(Other(text)) - diff --git a/fast4s-data/shared/src/main/scala/io/fast4s/data/HttpMethod.scala b/fast4s-data/shared/src/main/scala/io/fast4s/data/HttpMethod.scala index a5630f4..63333b4 100644 --- a/fast4s-data/shared/src/main/scala/io/fast4s/data/HttpMethod.scala +++ b/fast4s-data/shared/src/main/scala/io/fast4s/data/HttpMethod.scala @@ -16,31 +16,32 @@ enum HttpMethod(val verb: String): object HttpMethod: def apply(verb: String): HttpMethod = - val values = Head :: Options :: Patch :: Get :: Post :: Put :: Delete :: Connect :: Trace :: Nil + val values = + Head :: Options :: Patch :: Get :: Post :: Put :: Delete :: Connect :: Trace :: Nil values.find(m => m.verb.equals(verb)).getOrElse(Other(verb)) extension (method: HttpMethod) def toMethod: Method = method match - case HttpMethod.Get => Method.GET - case HttpMethod.Post => Method.POST - case HttpMethod.Put => Method.PUT - case HttpMethod.Delete => Method.DELETE + case HttpMethod.Get => Method.GET + case HttpMethod.Post => Method.POST + case HttpMethod.Put => Method.PUT + case HttpMethod.Delete => Method.DELETE case HttpMethod.Options => Method.OPTIONS - case HttpMethod.Patch => Method.PATCH - case HttpMethod.Head => Method.HEAD + case HttpMethod.Patch => Method.PATCH + case HttpMethod.Head => Method.HEAD case HttpMethod.Connect => Method.CONNECT - case HttpMethod.Trace => Method.TRACE - case _ => Method.ANY + case HttpMethod.Trace => Method.TRACE + case _ => Method.ANY extension (method: Method) def toHttpMethod: HttpMethod = method match - case Method.GET => HttpMethod.Get - case Method.POST => HttpMethod.Post - case Method.PUT => HttpMethod.Put - case Method.DELETE => HttpMethod.Delete + case Method.GET => HttpMethod.Get + case Method.POST => HttpMethod.Post + case Method.PUT => HttpMethod.Put + case Method.DELETE => HttpMethod.Delete case Method.OPTIONS => HttpMethod.Options - case Method.PATCH => HttpMethod.Patch - case Method.HEAD => HttpMethod.Head + case Method.PATCH => HttpMethod.Patch + case Method.HEAD => HttpMethod.Head case Method.CONNECT => HttpMethod.Connect - case Method.TRACE => HttpMethod.Trace - case Method.ANY => HttpMethod.Other("") \ No newline at end of file + case Method.TRACE => HttpMethod.Trace + case Method.ANY => HttpMethod.Other("") diff --git a/fast4s-data/shared/src/main/scala/io/fast4s/data/HttpStatus.scala b/fast4s-data/shared/src/main/scala/io/fast4s/data/HttpStatus.scala index ff8929e..be260ab 100644 --- a/fast4s-data/shared/src/main/scala/io/fast4s/data/HttpStatus.scala +++ b/fast4s-data/shared/src/main/scala/io/fast4s/data/HttpStatus.scala @@ -8,7 +8,8 @@ enum HttpStatus(val code: Int, val reason: String): case OK extends HttpStatus(200, "OK") case Created extends HttpStatus(201, "Created") case Accepted extends HttpStatus(202, "Accepted") - case NonAuthoritativeInformation extends HttpStatus(203, "Non-authoritative Information") + case NonAuthoritativeInformation + extends HttpStatus(203, "Non-authoritative Information") case NoContent extends HttpStatus(204, "No Content") case ResetContent extends HttpStatus(205, "Reset Content") case PartialContent extends HttpStatus(206, "Partial Content") @@ -30,7 +31,8 @@ enum HttpStatus(val code: Int, val reason: String): case NotFound extends HttpStatus(404, "Not Found") case MethodNotAllowed extends HttpStatus(405, "Method Not Allowed") case NotAcceptable extends HttpStatus(406, "Not Acceptable") - case ProxyAuthenticationRequired extends HttpStatus(407, "Proxy Authentication Required") + case ProxyAuthenticationRequired + extends HttpStatus(407, "Proxy Authentication Required") case RequestTimeout extends HttpStatus(408, "Request Timeout") case Conflict extends HttpStatus(409, "Conflict") case Gone extends HttpStatus(410, "Gone") @@ -39,7 +41,8 @@ enum HttpStatus(val code: Int, val reason: String): case PayloadTooLarge extends HttpStatus(413, "Payload Too Large") case RequestURITooLong extends HttpStatus(414, "Request-URI Too Long") case UnsupportedMediaType extends HttpStatus(415, "Unsupported Media Type") - case RequestedRangeNotSatisfiable extends HttpStatus(416, "Requested Range Not Satisfiable") + case RequestedRangeNotSatisfiable + extends HttpStatus(416, "Requested Range Not Satisfiable") case ExpectationFailed extends HttpStatus(417, "Expectation Failed") case ImAteapot extends HttpStatus(418, "I’m a teapot") case MisdirectedRequest extends HttpStatus(421, "Misdirected Request") @@ -49,22 +52,28 @@ enum HttpStatus(val code: Int, val reason: String): case UpgradeRequired extends HttpStatus(426, "Upgrade Required") case PreconditionRequired extends HttpStatus(428, "Precondition Required") case TooManyRequests extends HttpStatus(429, "Too Many Requests") - case RequestHeaderFieldsTooLarge extends HttpStatus(431, "Request Header Fields Too Large") - case ConnectionClosedWithoutResponse extends HttpStatus(444, "Connection Closed Without Response") - case UnavailableForLegalReasons extends HttpStatus(451, "Unavailable For Legal Reasons") + case RequestHeaderFieldsTooLarge + extends HttpStatus(431, "Request Header Fields Too Large") + case ConnectionClosedWithoutResponse + extends HttpStatus(444, "Connection Closed Without Response") + case UnavailableForLegalReasons + extends HttpStatus(451, "Unavailable For Legal Reasons") case ClientClosedRequest extends HttpStatus(499, "Client Closed Request") case InternalServerError extends HttpStatus(500, "Internal Server Error") case NotImplemented extends HttpStatus(501, "Not Implemented") case BadGateway extends HttpStatus(502, "Bad Gateway") case ServiceUnavailable extends HttpStatus(503, "Service Unavailable") case GatewayTimeout extends HttpStatus(504, "Gateway Timeout") - case HTTPVersionNotSupported extends HttpStatus(505, "HTTP Version Not Supported") + case HTTPVersionNotSupported + extends HttpStatus(505, "HTTP Version Not Supported") case VariantAlsoNegotiates extends HttpStatus(506, "Variant Also Negotiates") case InsufficientStorage extends HttpStatus(507, "Insufficient Storage") case LoopDetected extends HttpStatus(508, "Loop Detected") case NotExtended extends HttpStatus(510, "Not Extended") - case NetworkAuthenticationRequired extends HttpStatus(511, "Network Authentication Required") - case NetworkConnectTimeoutError extends HttpStatus(599, "Network Connect Timeout Error") + case NetworkAuthenticationRequired + extends HttpStatus(511, "Network Authentication Required") + case NetworkConnectTimeoutError + extends HttpStatus(599, "Network Connect Timeout Error") object HttpStatus: def make(code: Int): HttpStatus = @@ -132,4 +141,4 @@ object HttpStatus: case 510 => NotExtended case 511 => NetworkAuthenticationRequired case 599 => NetworkConnectTimeoutError - case _ => StatusCode(code) \ No newline at end of file + case _ => StatusCode(code) diff --git a/fast4s-data/shared/src/main/scala/io/fast4s/data/RawRequest.scala b/fast4s-data/shared/src/main/scala/io/fast4s/data/RawRequest.scala index ce7626a..66a21ba 100644 --- a/fast4s-data/shared/src/main/scala/io/fast4s/data/RawRequest.scala +++ b/fast4s-data/shared/src/main/scala/io/fast4s/data/RawRequest.scala @@ -1,5 +1,7 @@ package io.fast4s.data -case class RawRequest(body: String = "", - bodyRaw: Seq[Byte] = Nil, - headers: Headers = Map()) \ No newline at end of file +case class RawRequest( + body: String = "", + bodyRaw: Seq[Byte] = Nil, + headers: Headers = Map() +) diff --git a/fast4s-data/shared/src/main/scala/io/fast4s/data/Request.scala b/fast4s-data/shared/src/main/scala/io/fast4s/data/Request.scala index 195f831..24576e5 100644 --- a/fast4s-data/shared/src/main/scala/io/fast4s/data/Request.scala +++ b/fast4s-data/shared/src/main/scala/io/fast4s/data/Request.scala @@ -3,13 +3,13 @@ package io.fast4s.data import via.{Params, Query, RouteMatcher} case class Request( - method: HttpMethod, - target: String, - body: String = "", - contentType: ContentType = ContentType.Empty, - bodyRaw: Seq[Byte] = Nil, - headers: Headers = Map(), - params: Params = Params(), - query: Query = Query(), - matcher: RouteMatcher = Nil -) \ No newline at end of file + method: HttpMethod, + target: String, + body: String = "", + contentType: ContentType = ContentType.Empty, + bodyRaw: Seq[Byte] = Nil, + headers: Headers = Map(), + params: Params = Params(), + query: Query = Query(), + matcher: RouteMatcher = Nil +) diff --git a/fast4s-data/shared/src/main/scala/io/fast4s/data/Response.scala b/fast4s-data/shared/src/main/scala/io/fast4s/data/Response.scala index d01b2c8..706ce2f 100644 --- a/fast4s-data/shared/src/main/scala/io/fast4s/data/Response.scala +++ b/fast4s-data/shared/src/main/scala/io/fast4s/data/Response.scala @@ -10,50 +10,96 @@ case class Response( object Response: object Ok: - def apply(body: String = HttpStatus.OK.reason, contentType: ContentType = ContentType.Text): Response = + def apply( + body: String = HttpStatus.OK.reason, + contentType: ContentType = ContentType.Text + ): Response = ok(body, contentType) object NotFound: - def apply(body: String = HttpStatus.NotFound.reason, contentType: ContentType = ContentType.Text): Response = + def apply( + body: String = HttpStatus.NotFound.reason, + contentType: ContentType = ContentType.Text + ): Response = notFound(body, contentType) object ServerError: - def apply(body: String = HttpStatus.InternalServerError.reason, contentType: ContentType = ContentType.Text): Response = + def apply( + body: String = HttpStatus.InternalServerError.reason, + contentType: ContentType = ContentType.Text + ): Response = serverError(body, contentType) object BadRequest: - def apply(body: String = HttpStatus.BadRequest.reason, contentType: ContentType = ContentType.Text): Response = + def apply( + body: String = HttpStatus.BadRequest.reason, + contentType: ContentType = ContentType.Text + ): Response = badRequest(body, contentType) object Created: - def apply(body: String = HttpStatus.Created.reason, contentType: ContentType = ContentType.Text): Response = + def apply( + body: String = HttpStatus.Created.reason, + contentType: ContentType = ContentType.Text + ): Response = created(body, contentType) object Unauthorized: - def apply(body: String = HttpStatus.Unauthorized.reason, contentType: ContentType = ContentType.Text): Response = + def apply( + body: String = HttpStatus.Unauthorized.reason, + contentType: ContentType = ContentType.Text + ): Response = unauthorized(body, contentType) object Forbidden: - def apply(body: String = HttpStatus.Forbidden.reason, contentType: ContentType = ContentType.Text): Response = + def apply( + body: String = HttpStatus.Forbidden.reason, + contentType: ContentType = ContentType.Text + ): Response = forbiden(body, contentType) - def ok(body: String = "", contentType: ContentType = ContentType.Text): Response = + def ok( + body: String = "", + contentType: ContentType = ContentType.Text + ): Response = Response(HttpStatus.OK, contentType = contentType, body = body) - def created(body: String, contentType: ContentType = ContentType.Text): Response = + def created( + body: String, + contentType: ContentType = ContentType.Text + ): Response = Response(HttpStatus.Created, contentType = contentType, body = body) - def notFound(body: String = HttpStatus.NotFound.reason, contentType: ContentType = ContentType.Text): Response = + def notFound( + body: String = HttpStatus.NotFound.reason, + contentType: ContentType = ContentType.Text + ): Response = Response(HttpStatus.NotFound, contentType = contentType, body = body) - def serverError(body: String = HttpStatus.InternalServerError.reason, contentType: ContentType = ContentType.Text): Response = - Response(HttpStatus.InternalServerError, contentType = contentType, body = body) + def serverError( + body: String = HttpStatus.InternalServerError.reason, + contentType: ContentType = ContentType.Text + ): Response = + Response( + HttpStatus.InternalServerError, + contentType = contentType, + body = body + ) - def badRequest(body: String = HttpStatus.BadRequest.reason, contentType: ContentType = ContentType.Text): Response = + def badRequest( + body: String = HttpStatus.BadRequest.reason, + contentType: ContentType = ContentType.Text + ): Response = Response(HttpStatus.BadRequest, contentType = contentType, body = body) - def unauthorized(body: String = HttpStatus.Unauthorized.reason, contentType: ContentType = ContentType.Text): Response = + def unauthorized( + body: String = HttpStatus.Unauthorized.reason, + contentType: ContentType = ContentType.Text + ): Response = Response(HttpStatus.Unauthorized, contentType = contentType, body = body) - def forbiden(body: String = HttpStatus.Forbidden.reason, contentType: ContentType = ContentType.Text): Response = + def forbiden( + body: String = HttpStatus.Forbidden.reason, + contentType: ContentType = ContentType.Text + ): Response = Response(HttpStatus.Forbidden, contentType = contentType, body = body) diff --git a/fast4s-data/shared/src/main/scala/io/fast4s/data/data.scala b/fast4s-data/shared/src/main/scala/io/fast4s/data/data.scala index b25d73c..7e0a2d0 100644 --- a/fast4s-data/shared/src/main/scala/io/fast4s/data/data.scala +++ b/fast4s-data/shared/src/main/scala/io/fast4s/data/data.scala @@ -1,3 +1,3 @@ package io.fast4s.data -type Headers = Map[String, String] \ No newline at end of file +type Headers = Map[String, String] diff --git a/fast4s-example/js/src/main/scala/io/fast4s/example/AppServer.scala b/fast4s-example/js/src/main/scala/io/fast4s/example/AppServer.scala index 4a60bb7..aec7e28 100644 --- a/fast4s-example/js/src/main/scala/io/fast4s/example/AppServer.scala +++ b/fast4s-example/js/src/main/scala/io/fast4s/example/AppServer.scala @@ -8,24 +8,21 @@ import via.* object AppServer: - def serve(using HttpServerCreator): Int = - val logger: Enter = enter(GET): - req => - println(s"enter in ${req.target}") - req + val logger: Enter = enter(GET): req => + println(s"enter in ${req.target}") + req - val home: Route = route(GET, root): - _ => Response.ok("alive!") + val home: Route = route(GET, root): _ => + Response.ok("alive!") - val ping: Route = route(GET, root / "ping"): - _ => Response.ok("pong") + val ping: Route = route(GET, root / "ping"): _ => + Response.ok("pong") - val person: Route = route(GET, root / "person"): - _ => - val json = Person(1, "Ricardo").toJson - Response.ok(json, Json) + val person: Route = route(GET, root / "person"): _ => + val json = Person(1, "Ricardo").toJson + Response.ok(json, Json) HttpServerBuilder() .withRoutes( @@ -35,5 +32,3 @@ object AppServer: ) .build .serve - - diff --git a/fast4s-example/js/src/main/scala/io/fast4s/example/ExpressLike.scala b/fast4s-example/js/src/main/scala/io/fast4s/example/ExpressLike.scala index 10eeef8..d5feffc 100644 --- a/fast4s-example/js/src/main/scala/io/fast4s/example/ExpressLike.scala +++ b/fast4s-example/js/src/main/scala/io/fast4s/example/ExpressLike.scala @@ -6,49 +6,44 @@ import io.fast4s.example.models.Person object ExpressLike: - fast.get("/") { - _ => Response.ok("hello, world!") + fast.get("/") { _ => + Response.ok("hello, world!") } - fast.get("/user") { - (req: Request) => - Response.ok(s"hello, ${req.query.str("name").getOrElse("anonymous")}!") + fast.get("/user") { (req: Request) => + Response.ok(s"hello, ${req.query.str("name").getOrElse("anonymous")}!") } - fast.get("/err") { - _ => throw Exception("err") + fast.get("/err") { _ => + throw Exception("err") } - fast.get("/person") { - _ => Response.ok(Person(id=1, name = "Ricardo").toJson) + fast.get("/person") { _ => + Response.ok(Person(id = 1, name = "Ricardo").toJson) } - fast.post("/person") { - (req: Request) => - println(s"body = ${req.body}") - Response.ok(Person.fromJson(req.body).toJson) + fast.post("/person") { (req: Request) => + println(s"body = ${req.body}") + Response.ok(Person.fromJson(req.body).toJson) } - fast.recover { - (req, err) => - Response.ok(s"recovered! ${err.getMessage}") + fast.recover { (req, err) => + Response.ok(s"recovered! ${err.getMessage}") } - fast.intercept(404) { - (req, resp) => Response.ok("404") + fast.intercept(404) { (req, resp) => + Response.ok("404") } - fast.enter(Get, "/.*") { - req => - println(s"ns enter ${req.target}") - req + fast.enter(Get, "/.*") { req => + println(s"ns enter ${req.target}") + req } - fast.leave(Get, "/.*") { - (req, resp) => - println(s"ns leave ${req.target}") - resp + fast.leave(Get, "/.*") { (req, resp) => + println(s"ns leave ${req.target}") + resp } - def serve(using HttpServerCreator): Int = - fast.serve() \ No newline at end of file + def serve(using HttpServerCreator): Int = + fast.serve() diff --git a/fast4s-example/js/src/main/scala/io/fast4s/example/main.scala b/fast4s-example/js/src/main/scala/io/fast4s/example/main.scala index afc77c9..13a7aa9 100644 --- a/fast4s-example/js/src/main/scala/io/fast4s/example/main.scala +++ b/fast4s-example/js/src/main/scala/io/fast4s/example/main.scala @@ -3,9 +3,8 @@ package io.fast4s.example import fast4s.backend.node.async //import fast4s.requestBuilder - @main def main(args: String*): Int = { ExpressLike.serve - //AppServer.serve -} \ No newline at end of file + // AppServer.serve +} diff --git a/fast4s-example/js/src/main/scala/io/fast4s/example/models.scala b/fast4s-example/js/src/main/scala/io/fast4s/example/models.scala index d866e2d..ab4d031 100644 --- a/fast4s-example/js/src/main/scala/io/fast4s/example/models.scala +++ b/fast4s-example/js/src/main/scala/io/fast4s/example/models.scala @@ -13,7 +13,7 @@ object models: Encoder.typ[Person] |> Encoder.field("id", _.id) |> Encoder.field("name", _.name) - + val decoder: Decoder[Person] = Decoder.typ[Person] |> Decoder.field("id", (p, i: Int) => p.copy(id = i)) @@ -21,7 +21,4 @@ object models: def fromJson(s: String): Person = decoder.parse(s) - extension (p: Person) - def toJson: String = encoder.encodeObject(p) - - + extension (p: Person) def toJson: String = encoder.encodeObject(p) diff --git a/fast4s-example/native/src/main/scala/io/fast4s/example/AppServer.scala b/fast4s-example/native/src/main/scala/io/fast4s/example/AppServer.scala index a86ed96..113bf52 100644 --- a/fast4s-example/native/src/main/scala/io/fast4s/example/AppServer.scala +++ b/fast4s-example/native/src/main/scala/io/fast4s/example/AppServer.scala @@ -8,24 +8,21 @@ import io.fast4s.example.models.Person object AppServer: - def serve(using HttpServerCreator): Int = - val logger: Enter = enter(GET): - req => - println(s"enter in ${req.target}") - req + val logger: Enter = enter(GET): req => + println(s"enter in ${req.target}") + req - val home: Route = route(GET, root): - _ => Response.ok("alive!") + val home: Route = route(GET, root): _ => + Response.ok("alive!") - val ping: Route = route(GET, root / "ping"): - _ => Response.ok("pong") + val ping: Route = route(GET, root / "ping"): _ => + Response.ok("pong") - val person: Route = route(GET, root / "person"): - _ => - val json = Person(1, "Ricardo").toJson - Response.ok(json, Json) + val person: Route = route(GET, root / "person"): _ => + val json = Person(1, "Ricardo").toJson + Response.ok(json, Json) HttpServerBuilder() .withRoutes( @@ -35,5 +32,3 @@ object AppServer: ) .build .serve - - diff --git a/fast4s-example/native/src/main/scala/io/fast4s/example/ExpressLike.scala b/fast4s-example/native/src/main/scala/io/fast4s/example/ExpressLike.scala index 10eeef8..d5feffc 100644 --- a/fast4s-example/native/src/main/scala/io/fast4s/example/ExpressLike.scala +++ b/fast4s-example/native/src/main/scala/io/fast4s/example/ExpressLike.scala @@ -6,49 +6,44 @@ import io.fast4s.example.models.Person object ExpressLike: - fast.get("/") { - _ => Response.ok("hello, world!") + fast.get("/") { _ => + Response.ok("hello, world!") } - fast.get("/user") { - (req: Request) => - Response.ok(s"hello, ${req.query.str("name").getOrElse("anonymous")}!") + fast.get("/user") { (req: Request) => + Response.ok(s"hello, ${req.query.str("name").getOrElse("anonymous")}!") } - fast.get("/err") { - _ => throw Exception("err") + fast.get("/err") { _ => + throw Exception("err") } - fast.get("/person") { - _ => Response.ok(Person(id=1, name = "Ricardo").toJson) + fast.get("/person") { _ => + Response.ok(Person(id = 1, name = "Ricardo").toJson) } - fast.post("/person") { - (req: Request) => - println(s"body = ${req.body}") - Response.ok(Person.fromJson(req.body).toJson) + fast.post("/person") { (req: Request) => + println(s"body = ${req.body}") + Response.ok(Person.fromJson(req.body).toJson) } - fast.recover { - (req, err) => - Response.ok(s"recovered! ${err.getMessage}") + fast.recover { (req, err) => + Response.ok(s"recovered! ${err.getMessage}") } - fast.intercept(404) { - (req, resp) => Response.ok("404") + fast.intercept(404) { (req, resp) => + Response.ok("404") } - fast.enter(Get, "/.*") { - req => - println(s"ns enter ${req.target}") - req + fast.enter(Get, "/.*") { req => + println(s"ns enter ${req.target}") + req } - fast.leave(Get, "/.*") { - (req, resp) => - println(s"ns leave ${req.target}") - resp + fast.leave(Get, "/.*") { (req, resp) => + println(s"ns leave ${req.target}") + resp } - def serve(using HttpServerCreator): Int = - fast.serve() \ No newline at end of file + def serve(using HttpServerCreator): Int = + fast.serve() diff --git a/fast4s-example/native/src/main/scala/io/fast4s/example/main.scala b/fast4s-example/native/src/main/scala/io/fast4s/example/main.scala index c4dfad1..58d6110 100644 --- a/fast4s-example/native/src/main/scala/io/fast4s/example/main.scala +++ b/fast4s-example/native/src/main/scala/io/fast4s/example/main.scala @@ -3,9 +3,8 @@ package io.fast4s.example import fast4s.backend.beast.sync //import fast4s.requestBuilder - @main def main(args: String*): Int = { ExpressLike.serve - //AppServer.serve -} \ No newline at end of file + // AppServer.serve +} diff --git a/fast4s-example/native/src/main/scala/io/fast4s/example/models.scala b/fast4s-example/native/src/main/scala/io/fast4s/example/models.scala index 096d8f5..5232a9d 100644 --- a/fast4s-example/native/src/main/scala/io/fast4s/example/models.scala +++ b/fast4s-example/native/src/main/scala/io/fast4s/example/models.scala @@ -1,6 +1,6 @@ package io.fast4s.example -import decoda.{*, given } +import decoda.{*, given} import Decoder.given, Encoder.given object models: @@ -12,7 +12,7 @@ object models: Encoder.typ[Person] |> Encoder.field("id", _.id) |> Encoder.field("name", _.name) - + val decoder: Decoder[Person] = Decoder.typ[Person] |> Decoder.field("id", (p, i: Int) => p.copy(id = i)) @@ -20,7 +20,4 @@ object models: def fromJson(s: String): Person = decoder.parse(s) - extension (p: Person) - def toJson: String = encoder.encodeObject(p) - - + extension (p: Person) def toJson: String = encoder.encodeObject(p) diff --git a/fast4s-example/native/src/test/scala/io/fast4s/example/ServerHandleSpec.scala b/fast4s-example/native/src/test/scala/io/fast4s/example/ServerHandleSpec.scala index ecd95da..253f48c 100644 --- a/fast4s-example/native/src/test/scala/io/fast4s/example/ServerHandleSpec.scala +++ b/fast4s-example/native/src/test/scala/io/fast4s/example/ServerHandleSpec.scala @@ -1,49 +1,43 @@ package io.fast4s.example -import fast4s.{*, given } +import fast4s.{*, given} import fast4s.backend.beast.sync import org.scalatest.funsuite.AnyFunSuite class ServerHandleSpec extends AnyFunSuite: - test("request test"){ + test("request test") { - fast.get("/user") { - _ => Ok("pong") + fast.get("/user") { _ => + Ok("pong") } - fast.post("/user") { - req => - req.body match - case "ping" => Ok("pong") - case _ => BadRequest() + fast.post("/user") { req => + req.body match + case "ping" => Ok("pong") + case _ => BadRequest() } - fast.get("/user/:id") { - (req: Request) => - req.body match - case "ping" => Ok("pong") - case _ => BadRequest() + fast.get("/user/:id") { (req: Request) => + req.body match + case "ping" => Ok("pong") + case _ => BadRequest() } val server = fast.server.create() - + server .handle(Request(HttpMethod.Get, "/user")) match - case Response(HttpStatus.OK, "pong", _, _, _) => - case resp => fail(s"expected pong: $resp") + case Response(HttpStatus.OK, "pong", _, _, _) => + case resp => fail(s"expected pong: $resp") server .handle(Request(HttpMethod.Get, "/users")) match - case Response(HttpStatus.NotFound, _, _, _, _) => - case resp => fail(s"expected not found: $resp") + case Response(HttpStatus.NotFound, _, _, _, _) => + case resp => fail(s"expected not found: $resp") server .handle(Request(HttpMethod.Get, "/user", "ping")) match - case Response(HttpStatus.OK, "pong", _, _, _) => - case resp => fail(s"expected pong: $resp") + case Response(HttpStatus.OK, "pong", _, _, _) => + case resp => fail(s"expected pong: $resp") } - - - - diff --git a/fast4s-node/js/src/main/scala/fast4s/backend/node/node.scala b/fast4s-node/js/src/main/scala/fast4s/backend/node/node.scala index 431eddf..8ef1ef9 100644 --- a/fast4s-node/js/src/main/scala/fast4s/backend/node/node.scala +++ b/fast4s-node/js/src/main/scala/fast4s/backend/node/node.scala @@ -5,8 +5,8 @@ import io.fast4s.core.{HttpServerConfigs, HttpServerCreator, requestBuilder} package object node: - //given sync: HttpServerCreator = - // (cfg: HttpServerConfigs) => HttpServerSync(cfg) + // given sync: HttpServerCreator = + // (cfg: HttpServerConfigs) => HttpServerSync(cfg) - given async: HttpServerCreator = - (cfg: HttpServerConfigs) => HttpServerAsync(cfg) + given async: HttpServerCreator = + (cfg: HttpServerConfigs) => HttpServerAsync(cfg) diff --git a/fast4s-node/js/src/main/scala/io/fast4s/backend/node/HttpServerAsync.scala b/fast4s-node/js/src/main/scala/io/fast4s/backend/node/HttpServerAsync.scala index 4ac7fc7..7cb18ed 100644 --- a/fast4s-node/js/src/main/scala/io/fast4s/backend/node/HttpServerAsync.scala +++ b/fast4s-node/js/src/main/scala/io/fast4s/backend/node/HttpServerAsync.scala @@ -27,19 +27,24 @@ object Node: @js.native @JSImport("node:http", JSImport.Namespace) object Http extends js.Object: - def createServer(handler: js.Function2[IncomingMessage, ServerResponse, Unit]): Server = js.native + def createServer( + handler: js.Function2[IncomingMessage, ServerResponse, Unit] + ): Server = js.native extension (req: IncomingMessage) - /** Build the "complete request" bridge object expected by fast4s core (RawRequest). */ + /** Build the "complete request" bridge object expected by fast4s core + * (RawRequest). + */ def request(onComplete: Request => Unit): Unit = val headersMap: Map[String, String] = req.headers.iterator.map { case (k, v) => val valueStr = if js.isUndefined(v) || v == null then "" - else v match - case arr: js.Array[?] => - arr.map(_.toString).mkString(",") - case other => other.toString + else + v match + case arr: js.Array[?] => + arr.map(_.toString).mkString(",") + case other => other.toString k -> valueStr }.toMap @@ -68,19 +73,23 @@ object Node: catch case _: Throwable => "" val request = Request( target = req.url.getOrElse("/"), - method = req.method.map { s => HttpMethod(s) }.getOrElse(HttpMethod.Get), + method = + req.method.map { s => HttpMethod(s) }.getOrElse(HttpMethod.Get), body = bodyStr, bodyRaw = bodyRaw, - headers = headersMap) + headers = headersMap + ) onComplete(request) req - .on("data",onData) + .on("data", onData) .on("end", onEnd) () extension (resp: ServerResponse) - /** Write the "complete response" bridge object (fast4s Response) into Node's ServerResponse. */ + /** Write the "complete response" bridge object (fast4s Response) into + * Node's ServerResponse. + */ def respond(r: Response): Unit = val h = js.Dictionary.empty[String] @@ -88,7 +97,8 @@ object Node: r.headers.foreach { case (k, v) => h.update(k, v) } // Ensure content-type exists when fast4s has one - val hasContentType = r.headers.keys.exists(_.equalsIgnoreCase("content-type")) + val hasContentType = + r.headers.keys.exists(_.equalsIgnoreCase("content-type")) if !hasContentType then h.update("content-type", r.contentType.mimeType) resp.writeHead(r.status.code, h) @@ -114,18 +124,22 @@ object HttpServerAsync: def enter: Seq[NSEnter] = cfg.enter } - def handle(nodeReq: Node.IncomingMessage, nodeResp: Node.ServerResponse): Unit = + def handle( + nodeReq: Node.IncomingMessage, + nodeResp: Node.ServerResponse + ): Unit = nodeReq.request { req => val resp = HttpServer.handle(req) nodeResp.respond(resp) } -trait HttpServerAsync(val host: String, - val port: Int, - val workers: Int = 1) extends HttpServer: +trait HttpServerAsync(val host: String, val port: Int, val workers: Int = 1) + extends HttpServer: override def run: Int = Node.Http - .createServer { (nodeReq, nodeResp) => HttpServerAsync.handle(nodeReq, nodeResp) } + .createServer { (nodeReq, nodeResp) => + HttpServerAsync.handle(nodeReq, nodeResp) + } .listen(port, host, () => println(s"Server listen on http://$host:$port")) - 0 \ No newline at end of file + 0 diff --git a/fast4s-node/js/src/main/scala/io/fast4s/backend/node/HttpServerSync.scala b/fast4s-node/js/src/main/scala/io/fast4s/backend/node/HttpServerSync.scala index e90d6fc..56355c9 100644 --- a/fast4s-node/js/src/main/scala/io/fast4s/backend/node/HttpServerSync.scala +++ b/fast4s-node/js/src/main/scala/io/fast4s/backend/node/HttpServerSync.scala @@ -2,10 +2,7 @@ package io.fast4s.backend.node import io.fast4s.core.HttpServer - - -trait HttpServerSync(val host: String, - val port: Int, - val workers: Int = 1) extends HttpServer: +trait HttpServerSync(val host: String, val port: Int, val workers: Int = 1) + extends HttpServer: override def run: Int = ??? From 3695d8d21fd73c4f748a7b743e54279f19654678 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 12 Mar 2026 18:19:18 +0000 Subject: [PATCH 3/3] Add 'Reformat with scalafmt 3.8.6' to .git-blame-ignore-revs --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..d9c07aa --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Scala Steward: Reformat with scalafmt 3.8.6 +60984603f0870296af70b937e63be9c891ea702e