@@ -21,9 +21,9 @@ import akka.http.scaladsl.model.StatusCodes.NotFound
2121import akka .http .scaladsl .model .StatusCodes .OK
2222import akka .http .scaladsl .model .StatusCodes .BadRequest
2323import akka .http .scaladsl .model .StatusCodes .Conflict
24+
2425import java .time .Instant
2526import java .time .Clock
26-
2727import scala .language .postfixOps
2828import scala .concurrent .duration .DurationInt
2929import scala .util .Random
@@ -36,22 +36,29 @@ import common.WhiskProperties
3636import common .WskProps
3737import common .WskTestHelpers
3838import common .WskActorSystem
39- import common .rest .WskRestOperations
39+ import common .rest .{ RestResult , RunRestCmd , WskRestOperations }
4040import spray .json .DefaultJsonProtocol ._
4141import spray .json ._
4242import org .apache .openwhisk .core .entity ._
4343import org .apache .openwhisk .core .entity .size .SizeInt
4444import TestJsonArgs ._
45+ import akka .http .scaladsl .Http
46+ import akka .http .scaladsl .model .HttpMethods .POST
47+ import akka .http .scaladsl .model .{ContentTypes , HttpEntity , HttpHeader , HttpMethod , HttpRequest , HttpResponse , Uri }
48+ import akka .http .scaladsl .model .Uri .{Path , Query }
49+ import akka .http .scaladsl .model .headers .{Authorization , BasicHttpCredentials , RawHeader }
50+ import akka .util .ByteString
4551import org .apache .openwhisk .http .Messages
4652
4753/**
4854 * Tests for basic CLI usage. Some of these tests require a deployed backend.
4955 */
5056@ RunWith (classOf [JUnitRunner ])
51- class WskRestBasicUsageTests extends TestHelpers with WskTestHelpers with WskActorSystem {
57+ class WskRestBasicUsageTests extends TestHelpers with WskTestHelpers with WskActorSystem with RunRestCmd {
5258
5359 implicit val wskprops = WskProps ()
54- val wsk = new WskRestOperations
60+ implicit lazy override val executionContext = actorSystem.dispatcher
61+ val wsk = new WskRestOperations ()
5562 val defaultAction : Some [String ] = Some (TestUtils .getTestActionFilename(" hello.js" ))
5663 val usrAgentHeaderRegEx : String = """ \bUser-Agent\b": \[\s+"OpenWhisk\-CLI/1.\d+.*"""
5764
@@ -737,4 +744,86 @@ class WskRestBasicUsageTests extends TestHelpers with WskTestHelpers with WskAct
737744 wsk.trigger.delete(triggerName).statusCode shouldBe OK
738745 }
739746 }
747+
748+ it should " forward headers as parameters to the associated action" in withAssetCleaner(wskprops) {
749+ (wp, assetHelper) =>
750+ val guestNamespace = wsk.namespace.whois()
751+ val name = " triggerWithHeaders"
752+ val actionName = " params"
753+ val ruleName = " ruleWithHeaders"
754+
755+ assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
756+ trigger.create(name)
757+ }
758+
759+ assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
760+ action.create(actionName, Some (TestUtils .getTestActionFilename(" params.js" )))
761+ }
762+
763+ assetHelper.withCleaner(wsk.rule, ruleName) { (rule, _) =>
764+ rule.create(ruleName, trigger = name, action = actionName)
765+ rule.enable(ruleName)
766+ }
767+
768+ val path = Path (s " $basePath/namespaces/ $guestNamespace/triggers/ $name" )
769+
770+ val resp = requestEntityWithHeader(POST , path, List (RawHeader (" Foo" , " Bar" )))(wp)
771+ val result = new RestResult (resp.status.intValue, getTransactionId(resp), getRespData(resp))
772+
773+ withActivation(wsk.activation, result) { triggerActivation =>
774+ val ruleActivation = triggerActivation.logs.get.map(_.parseJson.convertTo[common.RuleActivationResult ]).head
775+ withActivation(wsk.activation, ruleActivation.activationId) { actionActivation =>
776+ actionActivation.response.result match {
777+ case Some (result) =>
778+ result.fields.get(" args" ) map { headers =>
779+ headers.asJsObject.fields.get(" __ow_headers" ) map { params =>
780+ params.asJsObject.fields.get(" foo" ) map { foo =>
781+ foo shouldBe JsString (" Bar" )
782+ }
783+ }
784+ }
785+
786+ case others =>
787+ fail(s " no result found: $others" )
788+
789+ }
790+ actionActivation.cause shouldBe None
791+ }
792+ }
793+ }
794+
795+ def requestEntityWithHeader (method : HttpMethod ,
796+ path : Path ,
797+ headers : List [HttpHeader ],
798+ params : Map [String , String ] = Map .empty,
799+ body : Option [String ] = None )(implicit wp : WskProps ): HttpResponse = {
800+ val credentials = wp.authKey.split(" :" )
801+ val creds = new BasicHttpCredentials (credentials(0 ), credentials(1 ))
802+
803+ // startsWith(http) includes https
804+ val hostWithScheme = if (wp.apihost.startsWith(" http" )) {
805+ Uri (wp.apihost)
806+ } else {
807+ Uri ().withScheme(" https" ).withHost(wp.apihost)
808+ }
809+
810+ val request = HttpRequest (
811+ method,
812+ hostWithScheme.withPath(path).withQuery(Query (params)),
813+ Authorization (creds) :: headers,
814+ entity =
815+ body.map(b => HttpEntity .Strict (ContentTypes .`application/json`, ByteString (b))).getOrElse(HttpEntity .Empty ))
816+ val response = Http ().singleRequest(request, connectionContext).flatMap { _.toStrict(toStrictTimeout) }.futureValue
817+
818+ logger.debug(this , s " Request: $request" )
819+ logger.debug(this , s " Response: $response" )
820+
821+ val validationErrors = validateRequestAndResponse(request, response)
822+ if (validationErrors.nonEmpty) {
823+ fail(
824+ s " HTTP request or response did not match the Swagger spec. \n Request: $request\n " +
825+ s " Response: $response\n Validation Error: $validationErrors" )
826+ }
827+ response
828+ }
740829}
0 commit comments