Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept non-standard status codes. #5149

Merged
merged 1 commit into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import akka.http.scaladsl.model.MediaType
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.MediaTypes._
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.StatusCode
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.headers._
Expand All @@ -40,7 +41,7 @@ import akka.http.scaladsl.model.headers.`Timeout-Access`
import akka.http.scaladsl.model.ContentType
import akka.http.scaladsl.model.ContentTypes
import akka.http.scaladsl.model.FormData
import akka.http.scaladsl.model.HttpMethods.{OPTIONS}
import akka.http.scaladsl.model.HttpMethods.OPTIONS
import akka.http.scaladsl.model.HttpCharsets
import akka.http.scaladsl.model.HttpResponse
import spray.json._
Expand Down Expand Up @@ -248,18 +249,19 @@ protected[core] object WhiskWebActionsApi extends Directives {

val body = fields.get("body")

val code = fields.get(rp.statusCode).map {
case JsNumber(c) =>
// the following throws an exception if the code is not a whole number or a valid code
StatusCode.int2StatusCode(c.toIntExact)
case JsString(c) =>
// parse the string to an Int (not a BigInt) matching JsNumber case match above
// c.toInt could throw an exception if the string isn't an integer
StatusCode.int2StatusCode(c.toInt)
val intCode = fields.get(rp.statusCode).map {
// the following throws an exception if the code is not a whole number or a valid code
case JsNumber(c) => c.toIntExact

// parse the string to an Int (not a BigInt) matching JsNumber case match above
// c.toInt could throw an exception if the string isn't an integer
case JsString(c) => c.toInt

case _ => throw new Throwable("Illegal status code")
}

val code: Option[StatusCode] = intCode.map(c => StatusCodes.getForKey(c).getOrElse(StatusCodes.custom(c, "")))

body.collect {
case JsString(str) if str.nonEmpty => interpretHttpResponse(code.getOrElse(OK), headers, str, transid)
case JsString(str) /* str.isEmpty */ => respondWithEmptyEntity(code.getOrElse(NoContent), headers)
Expand All @@ -268,7 +270,7 @@ protected[core] object WhiskWebActionsApi extends Directives {

} getOrElse {
// either the result was not a JsObject or there was an exception validating the
// response as an http result
// response as an http result (including an invalid status code)
terminate(BadRequest, Messages.invalidMedia(`message/http`))(transid, jsonPrettyPrinter)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.FormData
import akka.http.scaladsl.model.HttpEntity
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.HttpCharsets
import akka.http.scaladsl.model.HttpHeader
Expand Down Expand Up @@ -914,6 +915,21 @@ trait WebActionsApiBaseTests extends ControllerTestCommon with BeforeAndAfterEac
}
}

it should s"use non-standard action status code to terminate an http response (auth? ${creds.isDefined})" in {
implicit val tid = transid()

Seq(s"$systemId/proxy/export_c.http").foreach { path =>
allowedMethods.foreach { m =>
actionResult = Some(JsObject(webApiDirectives.statusCode -> JsNumber(444)))
invocationsAllowed += 1

m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(StatusCodes.custom(444, ""))
}
}
}
}

it should s"use default field projection for extension (auth? ${creds.isDefined})" in {
implicit val tid = transid()

Expand Down Expand Up @@ -1957,13 +1973,18 @@ trait WebActionsApiBaseTests extends ControllerTestCommon with BeforeAndAfterEac

it should s"allowed string based status code (auth? ${creds.isDefined})" in {
implicit val tid = transid()
invocationsAllowed += 2
invocationsAllowed += 3

actionResult = Some(JsObject(webApiDirectives.statusCode -> JsString("200")))
Head(s"$testRoutePath/$systemId/proxy/export_c.http") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}

actionResult = Some(JsObject(webApiDirectives.statusCode -> JsString("444")))
Head(s"$testRoutePath/$systemId/proxy/export_c.http") ~> Route.seal(routes(creds)) ~> check {
status should be(StatusCodes.custom(444, ""))
}

actionResult = Some(JsObject(webApiDirectives.statusCode -> JsString("xyz")))
Head(s"$testRoutePath/$systemId/proxy/export_c.http") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
Expand Down