Skip to content

Getting 405 Method Not Allowed from combined routes with authentication #651

Open
@TheDIM47

Description

After some research I found simple way to reproduce the problem:

def makeSimpleRoutes(authenticated: TypedHeader[IO, UserAuth :: HNil]): HttpRoutes[IO] = {
    val routes1 = new RhoRoutes[IO] {
      POST / pathVar[String]("orderId", "Order ID String") >>> authenticated |>>
        { (id: String, UserAuth: UserAuth) => Ok("good patch") }
    }
    val routes2 = new RhoRoutes[IO] {
      GET / pathVar[String]("orderId", "Order ID String") >>> authenticated |>>
        { (id: String, UserAuth: UserAuth) => Ok("good get") }
    }
    (routes1 and routes2).toRoutes(identity)
  }

Test:

    val httpRoutes = makeSimpleRoutesWithCustomTypes(failureResponse)
    val req = Request[IO](Method.POST, Uri(path = "/61f2f255bb9269fafaf50a10"))
    val response = httpRoutes.orNotFound.run(req).unsafeRunSync()
    response.status shouldBe Status.Forbidden

When authenticated returns FailureResponse, test failed with 405 "Method Not Allowed":

405 Method Not Allowed was not equal to 403 Forbidden
Expected :403 Forbidden
Actual   :405 Method Not Allowed

But, when authenticated returns SuccessResponse, test passed.

    val httpRoutes = makeSimpleRoutesWithCustomTypes(successResponse)
    val req = Request[IO](Method.POST, Uri(path = "/61f2f255bb9269fafaf50a10"))
    val response = httpRoutes.orNotFound.run(req).unsafeRunSync()
    response.status shouldBe Status.Ok

OK!

Where:

  val failureResponse: TypedHeader[IO, UserAuth :: HNil] =
    RhoDsl[IO].genericRequestHeaderCapture[UserAuth] { _: Request[IO] =>
      FailureResponse[IO](new ResponseReason(Api.Forbidden.pure(Result.Error("Not authorized"))))
    }

  val successResponse: TypedHeader[IO, UserAuth :: HNil] =
    RhoDsl[IO].genericRequestHeaderCapture[UserAuth] { _: Request[IO] =>
      SuccessResponse(defaultUser)
    }

But this code passed OK for both cases:

val myPathVar = pathVar[String]("orderId", "Order ID String")

def makeSimpleRoutes(authenticated: TypedHeader[IO, UserAuth :: HNil]): HttpRoutes[IO] = {
    val routes1 = new RhoRoutes[IO] {
      POST / myPathVar >>> authenticated |>>
        { (id: String, UserAuth: UserAuth) => Ok("good patch") }
    }
    val routes2 = new RhoRoutes[IO] {
      GET / myPathVar >>> authenticated |>>
        { (id: String, UserAuth: UserAuth) => Ok("good get") }
    }
    (routes1 and routes2).toRoutes(identity)
  }

If you'll change line (routes1 and routes2).toRoutes(identity)
to (routes2 and routes1).toRoutes(identity), you'll get 405 on GET (not on POST)

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions