refactor/tweaked the variable names

This commit is contained in:
hongwei 2026-01-21 14:05:20 +01:00
parent f6d095bf1b
commit ef6bff5698
4 changed files with 34 additions and 62 deletions

View File

@ -3,7 +3,7 @@ package code.api.util.http4s
import cats.effect._
import code.api.APIFailureNewStyle
import code.api.util.ErrorMessages._
import code.api.util.{CallContext => SharedCallContext}
import code.api.util.CallContext
import net.liftweb.common.{Failure => LiftFailure}
import net.liftweb.json.compactRender
import net.liftweb.json.JsonDSL._
@ -41,7 +41,7 @@ object ErrorResponseConverter {
/**
* Convert an error to http4s Response[IO]
*/
def toHttp4sResponse(error: Throwable, callContext: SharedCallContext): IO[Response[IO]] = {
def toHttp4sResponse(error: Throwable, callContext: CallContext): IO[Response[IO]] = {
error match {
case e: APIFailureNewStyle =>
apiFailureToResponse(e, callContext)
@ -53,7 +53,7 @@ object ErrorResponseConverter {
/**
* Convert APIFailureNewStyle to http4s Response
*/
def apiFailureToResponse(failure: APIFailureNewStyle, callContext: SharedCallContext): IO[Response[IO]] = {
def apiFailureToResponse(failure: APIFailureNewStyle, callContext: CallContext): IO[Response[IO]] = {
val errorJson = OBPErrorResponse(failure.failCode, failure.failMsg)
val status = org.http4s.Status.fromInt(failure.failCode).getOrElse(org.http4s.Status.BadRequest)
IO.pure(
@ -67,7 +67,7 @@ object ErrorResponseConverter {
/**
* Convert Box Failure to http4s Response
*/
def boxFailureToResponse(failure: LiftFailure, callContext: SharedCallContext): IO[Response[IO]] = {
def boxFailureToResponse(failure: LiftFailure, callContext: CallContext): IO[Response[IO]] = {
val errorJson = OBPErrorResponse(400, failure.msg)
IO.pure(
Response[IO](org.http4s.Status.BadRequest)
@ -80,7 +80,7 @@ object ErrorResponseConverter {
/**
* Convert unknown error to http4s Response
*/
def unknownErrorToResponse(e: Throwable, callContext: SharedCallContext): IO[Response[IO]] = {
def unknownErrorToResponse(e: Throwable, callContext: CallContext): IO[Response[IO]] = {
val errorJson = OBPErrorResponse(500, s"$UnknownError: ${e.getMessage}")
IO.pure(
Response[IO](org.http4s.Status.InternalServerError)
@ -93,7 +93,7 @@ object ErrorResponseConverter {
/**
* Create error response with specific status code and message
*/
def createErrorResponse(statusCode: Int, message: String, callContext: SharedCallContext): IO[Response[IO]] = {
def createErrorResponse(statusCode: Int, message: String, callContext: CallContext): IO[Response[IO]] = {
val errorJson = OBPErrorResponse(statusCode, message)
val status = org.http4s.Status.fromInt(statusCode).getOrElse(org.http4s.Status.BadRequest)
IO.pure(

View File

@ -4,7 +4,7 @@ import cats.effect._
import code.api.APIFailureNewStyle
import code.api.util.APIUtil.ResourceDoc
import code.api.util.ErrorMessages._
import code.api.util.{CallContext => SharedCallContext}
import code.api.util.CallContext
import com.openbankproject.commons.model.{Bank, BankAccount, BankId, AccountId, ViewId, BankIdAccountId, CounterpartyTrait, User, View}
import net.liftweb.common.{Box, Empty, Full, Failure => LiftFailure}
import net.liftweb.http.provider.HTTPParam
@ -24,7 +24,7 @@ import scala.language.higherKinds
*
* This file contains:
* - Http4sCallContextBuilder: Builds shared CallContext from http4s Request[IO]
* - Http4sVaultKeys: Vault keys for storing validated objects in request attributes
* - Http4sRequestAttributes: Request attribute keys for storing validated objects
* - ResourceDocMatcher: Matches http4s requests to ResourceDoc entries
* - ResourceDocMiddleware: Validation chain middleware for http4s
* - ErrorResponseConverter: Converts OBP errors to http4s Response[IO]
@ -35,10 +35,16 @@ import scala.language.higherKinds
* These keys allow middleware to pass validated objects to endpoint handlers.
* WIP
*/
object Http4sVaultKeys {
/**
* Request attribute keys for storing validated objects in http4s requests.
* These keys allow middleware to pass validated objects to endpoint handlers.
*
* Note: Uses http4s Vault (org.typelevel.vault.Key) for type-safe request attributes.
*/
object Http4sRequestAttributes {
// Use shared CallContext from code.api.util.ApiSession
val callContextKey: Key[SharedCallContext] =
Key.newKey[IO, SharedCallContext].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
val callContextKey: Key[CallContext] =
Key.newKey[IO, CallContext].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
val userKey: Key[User] =
Key.newKey[IO, User].unsafeRunSync()(cats.effect.unsafe.IORuntime.global)
@ -58,7 +64,7 @@ object Http4sVaultKeys {
/**
* Helper methods for accessing validated objects from request attributes
*/
def getCallContext(req: Request[IO]): Option[SharedCallContext] =
def getCallContext(req: Request[IO]): Option[CallContext] =
req.attributes.lookup(callContextKey)
def getUser(req: Request[IO]): Option[User] =
@ -91,12 +97,12 @@ object Http4sCallContextBuilder {
*
* @param request The http4s request
* @param apiVersion The API version string (e.g., "v7.0.0")
* @return IO[SharedCallContext] with all request data populated
* @return IO[CallContext] with all request data populated
*/
def fromRequest(request: Request[IO], apiVersion: String): IO[SharedCallContext] = {
def fromRequest(request: Request[IO], apiVersion: String): IO[CallContext] = {
for {
body <- request.bodyText.compile.string.map(s => if (s.isEmpty) None else Some(s))
} yield SharedCallContext(
} yield CallContext(
url = request.uri.renderString,
verb = request.method.name,
implementedInVersion = apiVersion,
@ -316,9 +322,9 @@ object ResourceDocMatcher {
* @return Updated CallContext with resourceDocument and operationId set
*/
def attachToCallContext(
callContext: SharedCallContext,
callContext: CallContext,
resourceDoc: ResourceDoc
): SharedCallContext = {
): CallContext = {
callContext.copy(
resourceDocument = Some(resourceDoc),
operationId = Some(resourceDoc.operationId)
@ -336,5 +342,5 @@ case class ValidatedContext(
bankAccount: Option[BankAccount],
view: Option[View],
counterparty: Option[CounterpartyTrait],
callContext: SharedCallContext
callContext: CallContext
)

View File

@ -9,7 +9,7 @@ import code.api.util.APIUtil.ResourceDoc
import code.api.util.ErrorMessages._
import code.api.util.NewStyle
import code.api.util.newstyle.ViewNewStyle
import code.api.util.{CallContext => SharedCallContext}
import code.api.util.CallContext
import com.openbankproject.commons.model.{Bank, BankAccount, BankId, AccountId, ViewId, BankIdAccountId, CounterpartyTrait, User, View}
import net.liftweb.common.{Box, Empty, Full, Failure => LiftFailure}
import org.http4s._
@ -192,7 +192,7 @@ object ResourceDocMiddleware extends MdcLoggable{
case Left(errorResponse) => IO.pure(errorResponse)
case Right((bankOpt, cc3)) =>
// Step 4: Account validation (if ACCOUNT_ID in path)
val accountResult: IO[Either[Response[IO], (Option[BankAccount], SharedCallContext)]] =
val accountResult: IO[Either[Response[IO], (Option[BankAccount], CallContext)]] =
(pathParams.get("BANK_ID"), pathParams.get("ACCOUNT_ID")) match {
case (Some(bankIdStr), Some(accountIdStr)) =>
IO.fromFuture(IO(NewStyle.function.getBankAccount(BankId(bankIdStr), AccountId(accountIdStr), Some(cc3)))).attempt.flatMap {
@ -211,7 +211,7 @@ object ResourceDocMiddleware extends MdcLoggable{
case Left(errorResponse) => IO.pure(errorResponse)
case Right((accountOpt, cc4)) =>
// Step 5: View validation (if VIEW_ID in path)
val viewResult: IO[Either[Response[IO], (Option[View], SharedCallContext)]] =
val viewResult: IO[Either[Response[IO], (Option[View], CallContext)]] =
(pathParams.get("BANK_ID"), pathParams.get("ACCOUNT_ID"), pathParams.get("VIEW_ID")) match {
case (Some(bankIdStr), Some(accountIdStr), Some(viewIdStr)) =>
val bankIdAccountId = BankIdAccountId(BankId(bankIdStr), AccountId(accountIdStr))
@ -229,7 +229,7 @@ object ResourceDocMiddleware extends MdcLoggable{
case Left(errorResponse) => IO.pure(errorResponse)
case Right((viewOpt, cc5)) =>
// Step 6: Counterparty validation (if COUNTERPARTY_ID in path)
val counterpartyResult: IO[Either[Response[IO], (Option[CounterpartyTrait], SharedCallContext)]] =
val counterpartyResult: IO[Either[Response[IO], (Option[CounterpartyTrait], CallContext)]] =
(pathParams.get("BANK_ID"), pathParams.get("ACCOUNT_ID"), pathParams.get("COUNTERPARTY_ID")) match {
case (Some(bankIdStr), Some(accountIdStr), Some(counterpartyIdStr)) =>
IO.fromFuture(IO(NewStyle.function.getCounterpartyTrait(BankId(bankIdStr), AccountId(accountIdStr), counterpartyIdStr, Some(cc5)))).attempt.flatMap {
@ -247,12 +247,12 @@ object ResourceDocMiddleware extends MdcLoggable{
case Left(errorResponse) => IO.pure(errorResponse)
case Right((counterpartyOpt, finalCC)) =>
// All validations passed - store validated context and invoke route
var updatedReq = req.withAttribute(Http4sVaultKeys.callContextKey, finalCC)
boxUser.toOption.foreach { user => updatedReq = updatedReq.withAttribute(Http4sVaultKeys.userKey, user) }
bankOpt.foreach { bank => updatedReq = updatedReq.withAttribute(Http4sVaultKeys.bankKey, bank) }
accountOpt.foreach { account => updatedReq = updatedReq.withAttribute(Http4sVaultKeys.bankAccountKey, account) }
viewOpt.foreach { view => updatedReq = updatedReq.withAttribute(Http4sVaultKeys.viewKey, view) }
counterpartyOpt.foreach { counterparty => updatedReq = updatedReq.withAttribute(Http4sVaultKeys.counterpartyKey, counterparty) }
var updatedReq = req.withAttribute(Http4sRequestAttributes.callContextKey, finalCC)
boxUser.toOption.foreach { user => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.userKey, user) }
bankOpt.foreach { bank => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.bankKey, bank) }
accountOpt.foreach { account => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.bankAccountKey, account) }
viewOpt.foreach { view => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.viewKey, view) }
counterpartyOpt.foreach { counterparty => updatedReq = updatedReq.withAttribute(Http4sRequestAttributes.counterpartyKey, counterparty) }
routes.run(updatedReq).getOrElseF(IO.pure(Response[IO](org.http4s.Status.NotFound)))
}
}

View File

@ -1,34 +0,0 @@
package code.api.util
/**
* Http4s support package for OBP API.
*
* This package provides http4s-specific utilities for:
* - Building CallContext from http4s requests
* - Storing validated objects in request attributes (Vault keys)
* - Matching requests to ResourceDoc entries
* - ResourceDoc-driven validation middleware
* - Error response conversion
*
* Usage:
* {{{
* import code.api.util.http4s._
*
* // Build CallContext from request
* val cc = Http4sCallContextBuilder.fromRequest(request, "v7.0.0")
*
* // Access validated objects from request attributes
* val user = Http4sVaultKeys.getUser(request)
* val bank = Http4sVaultKeys.getBank(request)
*
* // Apply middleware to routes
* val wrappedRoutes = ResourceDocMiddleware.apply(resourceDocs)(routes)
*
* // Convert errors to http4s responses
* ErrorResponseConverter.unknownErrorToResponse(error, callContext)
* }}}
*/
package object http4s {
// Re-export types for convenience
type SharedCallContext = code.api.util.CallContext
}