From 7cb5416ad4a747afaf5f9d1909c87528f9d03073 Mon Sep 17 00:00:00 2001 From: zwiterrion Date: Fri, 24 May 2024 15:45:25 +0200 Subject: [PATCH] better integration and fix graphql proxy to REST plugin --- otoroshi/app/next/plugins/graphql.scala | 7 +- .../app/wasm/httpwasm/HttpWasmState.scala | 219 ++++++++++-------- otoroshi/app/wasm/httpwasm/functions.scala | 39 +++- otoroshi/app/wasm/httpwasm/httpwasm.scala | 214 ++++++++--------- .../{RequestState.scala => utils.scala} | 34 ++- otoroshi/lib/wasm4s-bundle_2.12-dev.jar | Bin 5910267 -> 5910303 bytes 6 files changed, 291 insertions(+), 222 deletions(-) rename otoroshi/app/wasm/httpwasm/{RequestState.scala => utils.scala} (69%) diff --git a/otoroshi/app/next/plugins/graphql.scala b/otoroshi/app/next/plugins/graphql.scala index 049e9a879..69dba64be 100644 --- a/otoroshi/app/next/plugins/graphql.scala +++ b/otoroshi/app/next/plugins/graphql.scala @@ -100,7 +100,7 @@ object GraphQLQueryConfig { "query" -> o.query, "timeout" -> o.timeout, "response_path" -> o.responsePath.map(JsString.apply).getOrElse(JsNull).asValue, - "response_filter" -> o.responsePath.map(JsString.apply).getOrElse(JsNull).asValue + "response_filter" -> o.responseFilter.map(JsString.apply).getOrElse(JsNull).asValue ) } } @@ -1164,7 +1164,10 @@ class GraphQLBackend extends NgBackendCall { builder = customBuilder, initialData = config.initialData.map(_.as[JsObject]).getOrElse(JsObject.empty), maxDepth = config.maxDepth, - variables = (jsonBody \ "variables").asOpt[JsValue].getOrElse(Json.obj()).as[JsObject] + variables = (jsonBody \ "variables").asOpt[JsValue] + .getOrElse(Json.obj()) + .asOpt[JsObject] + .getOrElse(Json.obj()) ) case None => jsonResponse(400, Json.obj("error" -> "query field missing")).future } diff --git a/otoroshi/app/wasm/httpwasm/HttpWasmState.scala b/otoroshi/app/wasm/httpwasm/HttpWasmState.scala index 5d7ee14e5..7b395d465 100644 --- a/otoroshi/app/wasm/httpwasm/HttpWasmState.scala +++ b/otoroshi/app/wasm/httpwasm/HttpWasmState.scala @@ -1,20 +1,21 @@ package otoroshi.wasm.httpwasm +import akka.stream.Materializer import akka.stream.scaladsl.Source import akka.util.ByteString import com.sun.jna.Pointer import org.extism.sdk.{ExtismCurrentPlugin, HostFunction} import otoroshi.env.Env import otoroshi.utils.syntax.implicits._ -import otoroshi.wasm.httpwasm.api.{LogLevel, _} +import otoroshi.wasm.httpwasm.api.{BodyKind, LogLevel, _} import play.api.Logger -import scala.concurrent.Await +import scala.concurrent.{Await, ExecutionContext} import scala.concurrent.duration.DurationInt class HttpWasmState(env: Env) { - val logger = Logger("otoroshi-proxy-wasm") + val logger = Logger("otoroshi-http-wasm") val u32Len = 4 @@ -23,47 +24,51 @@ class HttpWasmState(env: Env) { throw new NotImplementedError(s"proxy state method '${name}' is not implemented") } - def enableFeatures(vmData: HttpWasmVmData, features: Int): Int = { - vmData.features = Features(features) - features + def enableFeatures(vmData: HttpWasmVmData, features: Int)(implicit mat: Materializer, ec: ExecutionContext): Int = { + vmData.features = vmData.features.withEnabled(features) + + if (vmData.features.isEnabled(Feature.FeatureBufferRequest)) { + vmData.request.body.runFold(ByteString.empty)(_ ++ _).map { b => + vmData.bufferedRequestBody = b.some + } + } + + if (vmData.features.isEnabled(Feature.FeatureBufferResponse)) { + vmData.response.body.runFold(ByteString.empty)(_ ++ _).map { b => + vmData.bufferedResponseBody = b.some + } + } + + vmData.features.f } def getConfig(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, buf: Int, bufLimit: Int) = { writeIfUnderLimit(plugin, buf, bufLimit, ByteString(vmData.config.stringify)) } - def writeIfUnderLimit(plugin: ExtismCurrentPlugin, offset: Int, limit: Int, v: ByteString): Int = { + private def writeIfUnderLimit(plugin: ExtismCurrentPlugin, offset: Int, limit: Int, v: ByteString): Int = { val vLen = v.length if (vLen > limit || vLen == 0) { return vLen } - println("vLen", vLen) val memory: Pointer = plugin.customMemoryGet() - println("memory", memory) memory.write(offset, v.toArray, 0, vLen) - println("return vLen", vLen) vLen } - def writeNullTerminated(plugin: ExtismCurrentPlugin, buf: Int, bufLimit: Int, input: Seq[String]): BigInt = { + private def writeNullTerminated(plugin: ExtismCurrentPlugin, buf: Int, bufLimit: Int, input: Seq[String]): BigInt = { val count = input.length if (count == 0) { return 0 } - println(s"writeNullTerminated buf $buf - bufLimit $bufLimit") - val encodedInput = input.map(i => ByteString(i)) val byteCount = encodedInput.foldLeft(0) { case (acc, i) => acc + i.length } - println(s"byteCount $byteCount input $input count $count") - val countLen = (count << 32) | BigInt(byteCount) - println(s"countLen $countLen") - if (byteCount > bufLimit) { return countLen } @@ -83,14 +88,12 @@ class HttpWasmState(env: Env) { countLen } - def writeStringIfUnderLimit( + private def writeStringIfUnderLimit( plugin: ExtismCurrentPlugin, offset: Int, limit: Int, v: String - ): Int = { - this.writeIfUnderLimit(plugin, offset, limit, ByteString(v)) - } + ): Int = this.writeIfUnderLimit(plugin, offset, limit, ByteString(v)) def getHeaderNames( plugin: ExtismCurrentPlugin, @@ -99,7 +102,6 @@ class HttpWasmState(env: Env) { buf: Int, bufLimit: Int, ): BigInt = { - println("get headers names") val headers = vmData.headers(kind) val headerNames = headers.keys.toSeq @@ -124,19 +126,7 @@ class HttpWasmState(env: Env) { val n = this.mustReadString(plugin, "name", name, nameLen).toLowerCase() val value = headers.get(n) - var values: Seq[String] = Seq.empty - - value.foreach(value => { - n match { - // TODO(anuraaga): date is not mentioned as a header where duplicates are discarded. - // However, since it has a comma inside, it seems it must be handled as a single - // string. Double-check this. - case "date" | "age" | "authorization" | "content - length" | "content - type" | "etag" | "expires" | "from" | "host" | "if - modified - since" | "if - unmodified - since" | "last - modified" | "location" | "max - forwards" | "proxy - authorization" | "referer" | "retry - after" | "server" | "user - agent" => - values = Seq(value) - case "cookie" => values = value.split("; ") - case _ => values = value.split(", ") - } - }) + val values: Seq[String] = value.map(value => value.split("; ").toSeq).getOrElse(Seq.empty) this.writeNullTerminated(plugin, buf, bufLimit, values) } @@ -152,25 +142,24 @@ class HttpWasmState(env: Env) { case "1.1" => httpVersion = "HTTP/1.1" case "2" => httpVersion = "HTTP/2.0" case "2.0" => httpVersion = "HTTP/2.0" + case _ => httpVersion = httpVersion } - println(s"get protocol version $httpVersion") - -// vmData.setRequest(vmData.request.copy(version = httpVersion)) - this.writeStringIfUnderLimit (plugin, buf, bufLimit, httpVersion) } + def getSourceAddr(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, buf: Int, bufLimit: Int): Int = { + this.writeStringIfUnderLimit (plugin, buf, bufLimit, vmData.remoteAddress.get) + } + def getStatusCode(vmData: HttpWasmVmData): Int = vmData.requestStatusCode def getUri(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, buf: Int, bufLimit: Int): Int = { - println("get_uri") val uri = vmData.request.relativeUri this.writeStringIfUnderLimit (plugin, buf, bufLimit, if (uri.isEmpty) "/" else uri) } def log(plugin: ExtismCurrentPlugin, level: LogLevel, buf: Int, bufLimit: Int) = { - println("calling log function", level, buf, bufLimit) val s = mustReadString(plugin, "log", buf, bufLimit) level match { @@ -178,61 +167,111 @@ class HttpWasmState(env: Env) { case LogLevel.LogLevelInfo => logger.info(s) case LogLevel.LogLevelWarn => logger.warn(s) case LogLevel.LogLevelError => logger.error(s) + case _ => throw new Exception("invalid log level") } } def logEnabled(level: LogLevel): Int = { - println("calling log_enabled", level) if (level != LogLevel.LogLevelDebug) { return 1 } 0 } - def readBody(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, kind: BodyKind, buf: Int, bufLimit: Int): BigInt = { - val memory = plugin.customMemoryGet() + private def mustHeaderMutable(vmData: HttpWasmVmData, op: String, kind: HeaderKind) { + kind match { + case HeaderKind.HeaderKindRequest => mustBeforeNext(vmData, op, "request header") + case HeaderKind.HeaderKindResponse => mustBeforeNextOrFeature(vmData, Feature.FeatureBufferResponse, op, "response header") + case HeaderKind.HeaderKindRequestTrailers => mustBeforeNext(vmData, op, "request trailer") + case HeaderKind.HeaderKindResponseTrailers => mustBeforeNextOrFeature(vmData, Feature.FeatureBufferResponse, op, "response trailer") + } + } - if (kind == BodyKind.BodyKindRequest) { - val body: ByteString = Await.result(vmData.request.body.runFold(ByteString.empty)(_ ++ _)(env.otoroshiMaterializer), 10.seconds) - val start = vmData.requestBodyReadIndex - val end = Math.min (start + bufLimit, body.length) - val slice = body.slice(start, end) + private def mustBeforeNext(vmData: HttpWasmVmData, op: String, kind: String) { + if (vmData.afterNext) { + throw new RuntimeException(s"can't $op $kind after next handler") + } + } - memory.write(buf, slice.toArray, 0, slice.length) - vmData.requestBodyReadIndex = end - if (end == body.length) { - return (1 << 32) | BigInt (slice.length) - } - return BigInt (slice.length); - } + private def mustBeforeNextOrFeature(vmData: HttpWasmVmData, feature: Feature, op: String, kind: String): Unit = { + if (!vmData.afterNext) { + // Assume this is serving a response from the guest. + } else if (vmData.features.isEnabled(feature)) { + // Assume the guest is overwriting the response from next. + } else { + throw new RuntimeException(s"can't $op $kind after next handler unless " + + s"${Feature.toString(feature)} is enabled") + } + } - if (kind != BodyKind.BodyKindResponse) { - throw new RuntimeException(s"Unknown body kind $kind") + private def _readBody(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, buf: Int, bufLimit: Int, body: ByteString, kind: BodyKind): BigInt = { + // buf_limit 0 serves no purpose as implementations won't return EOF on it. + if (bufLimit == 0) { + throw new RuntimeException("buf_limit==0 reading body") } - val body = Await.result(vmData.response.body.runFold(ByteString.empty)(_ ++ _)(env.otoroshiMaterializer), 10.seconds) - -// if (buffer.isEmpty) { -// throw new Error(s"Response body not buffered") -// } + val memory = plugin.customMemoryGet() - val start = vmData.responseBodyReadIndex - val end = Math.min(start + bufLimit, body.length) + val start = kind match { + case BodyKind.BodyKindRequest => vmData.requestBodyReadIndex + case BodyKind.BodyKindResponse => vmData.requestBodyReadIndex + case _ => throw new Exception("invalid body kind") + } + val end = Math.min (start + bufLimit, body.length) val slice = body.slice(start, end) + memory.write(buf, slice.toArray, 0, slice.length) + kind match { + case BodyKind.BodyKindRequest => + vmData.requestBodyReadIndex = end + case BodyKind.BodyKindResponse => + vmData.responseBodyReadIndex = end + } - vmData.responseBodyReadIndex = end if (end == body.length) { return (1 << 32) | BigInt (slice.length) } BigInt (slice.length) +} + + + def readBody(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, kind: BodyKind, buf: Int, bufLimit: Int): BigInt = { + val body = kind match { + case BodyKind.BodyKindRequest => + mustBeforeNextOrFeature(vmData, Feature.FeatureBufferRequest, "read", BodyKind.toString(BodyKind.BodyKindRequest)) + + if (vmData.bufferedRequestBody.isEmpty) { + vmData.bufferedRequestBody = Some(Await.result(vmData.request.body.runFold(ByteString.empty)(_ ++ _) + (env.otoroshiMaterializer), 10.seconds)) + } + + vmData.bufferedRequestBody.get + + case BodyKind.BodyKindResponse => + mustBeforeNextOrFeature(vmData, Feature.FeatureBufferResponse, "read", BodyKind.toString(BodyKind.BodyKindResponse)) + + + if (vmData.bufferedResponseBody.isEmpty) { + vmData.bufferedResponseBody = Some(Await.result(vmData.response.body.runFold(ByteString.empty)(_ ++ _) + (env.otoroshiMaterializer), 10.seconds)) + } + + vmData.bufferedResponseBody.get + } + + _readBody(plugin, vmData, buf, bufLimit, body, kind) } - def setMethod(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, name: Int, nameLen: Int) { - val method = this.mustReadString(plugin, "method", name, nameLen) - println(s"reading method from set method - $name - $nameLen - $method") + def setMethod(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, method: Int, methodLen: Int) { + mustBeforeNext(vmData, "set", "method") + + if (methodLen == 0) { + throw new RuntimeException("HTTP method cannot be empty") + } - vmData.setRequest(vmData.request.copy(method = method)) + val readMethod = this.mustReadString(plugin, "method", method, methodLen) + + vmData.setMethod(readMethod) } def writeBody(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, kind: BodyKind, body: Int, bodyLen: Int) = { @@ -244,14 +283,7 @@ class HttpWasmState(env: Env) { b = this.mustRead(plugin, "body", body, bodyLen) } - println(s"write body $b - $body - $bodyLen") - - kind match { - case BodyKind.BodyKindRequest => - vmData.setRequest(vmData.request.copy(body = Source.single(b))) - case BodyKind.BodyKindResponse => - vmData.setResponse(vmData.response.copy(body = Source.single(b))) - } + vmData.setBody(Source.single(b), kind) } def addHeader( @@ -267,6 +299,8 @@ class HttpWasmState(env: Env) { throw new RuntimeException("HTTP header name cannot be empty") } + mustHeaderMutable(vmData, "add", kind) + val n = this.mustReadString (plugin, "name", name, nameLen) val v = this.mustReadString (plugin, "value", value, valueLen) @@ -290,11 +324,11 @@ class HttpWasmState(env: Env) { throw new RuntimeException("HTTP header name cannot be empty") } + mustHeaderMutable(vmData, "set", kind) + val n = this.mustReadString (plugin, "name", name, nameLen) val v = this.mustReadString (plugin, "value", value, valueLen) - println(s"Set header with $kind - $name - $value") - vmData.setHeader (kind, n, Seq(v)) } @@ -308,6 +342,8 @@ class HttpWasmState(env: Env) { throw new RuntimeException ("HTTP header name cannot be empty") } + mustHeaderMutable(vmData, "remove", kind) + val n = this.mustReadString (plugin, "name", name, nameLen) vmData.removeHeader (kind, n) } @@ -316,8 +352,9 @@ class HttpWasmState(env: Env) { vmData.setResponse(vmData.response.copy(status = statusCode)) } - def setUri(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, uri: Int, uriLen: Int) = { - println(s"set_uri $uri $uriLen") + def setUri(plugin: ExtismCurrentPlugin, vmData: HttpWasmVmData, uri: Int, uriLen: Int): Unit = { + + mustBeforeNext(vmData, "set", "uri") val u = if (uriLen > 0) { this.mustReadString(plugin, "uri", uri, uriLen) @@ -325,11 +362,10 @@ class HttpWasmState(env: Env) { "" } - vmData.setRequest(vmData.request.copy(url = u)) - println(s"set_uri $u") + vmData.setUri(u) } - def mustReadString( + private def mustReadString( plugin: ExtismCurrentPlugin, fieldName: String, offset: Int, @@ -342,7 +378,7 @@ class HttpWasmState(env: Env) { this.mustRead(plugin, fieldName, offset, byteCount).utf8String } - def mustRead( + private def mustRead( plugin: ExtismCurrentPlugin, fieldName: String, offset: Int, @@ -353,17 +389,6 @@ class HttpWasmState(env: Env) { } val memory: Pointer = plugin.customMemoryGet() - - // TODO - get memory size from RUST - // if ( - // offset >= memory.length || - // offset + byteCount >= this.memoryBuffer.length - // ) { - // throw new Error ( - // `out of memory reading ${fieldName}, offset: ${offset}, byteCount: ${byteCount}`, - // ); - // } - ByteString(memory.share(offset).getByteArray(0, byteCount)) } } diff --git a/otoroshi/app/wasm/httpwasm/functions.scala b/otoroshi/app/wasm/httpwasm/functions.scala index f57ae94a3..0820ae4c0 100644 --- a/otoroshi/app/wasm/httpwasm/functions.scala +++ b/otoroshi/app/wasm/httpwasm/functions.scala @@ -2,6 +2,7 @@ package otoroshi.wasm.httpwasm import akka.stream.Materializer import akka.stream.scaladsl.Source +import akka.util.ByteString import io.otoroshi.wasm4s.scaladsl._ import org.extism.sdk.{ExtismCurrentPlugin, HostFunction, HostUserData, LibExtism} import otoroshi.env.Env @@ -24,7 +25,11 @@ case class HttpWasmVmData( var features: Features = Features(3 | Feature.FeatureBufferRequest.value | Feature.FeatureBufferResponse.value | Feature.FeatureTrailers.value), var nextCalled: Boolean = false, var requestBodyReadIndex: Int = 0, - var responseBodyReadIndex: Int = 0 + var responseBodyReadIndex: Int = 0, + var bufferedRequestBody: Option[ByteString] = None, + var bufferedResponseBody: Option[ByteString] = None, + var afterNext: Boolean = false, + var remoteAddress: Option[String] = None ) extends HostUserData with WasmVmData { def headers(kind: HeaderKind): Map[String, String] = { @@ -44,8 +49,23 @@ case class HttpWasmVmData( response = newResponse } + def setMethod(method: String) = { + setRequest(request.copy(method = method)) + } + + def setUri(uri: String) = { + setRequest(request.copy(url = uri)) + } + + def setBody(body: Source[ByteString, _], bodyKind: BodyKind) = { + bodyKind match { + case BodyKind.BodyKindRequest => setRequest(request.copy(body = body)) + case BodyKind.BodyKindResponse => setResponse(response.copy(body = body)) + } + + } + def setHeader(kind: HeaderKind, key: String, value: Seq[String]) = { - println("set header", kind, key, value) kind match { case HeaderKind.HeaderKindRequest => setRequest(request.copy(headers = request.headers ++ Map(key -> value.head))) case HeaderKind.HeaderKindResponse => setResponse(response.copy(headers = response.headers ++ Map(key -> value.head))) @@ -75,7 +95,8 @@ object HttpWasmVmData { } object AdministrativeFunctions { - def all(state: HttpWasmState, getCurrentVmData: () => HttpWasmVmData) = { + def all(state: HttpWasmState, getCurrentVmData: () => HttpWasmVmData) + (implicit mat: Materializer, ec: ExecutionContext) = { Seq( new HostFunction[EnvUserData]( "enable_features", @@ -156,8 +177,6 @@ object HeaderFunctions { HeaderKind.fromValue(params(0).v.i32), params(1).v.i32, params(2).v.i32).longValue() - - println(s"ending get_header_names with ${returns(0).v.i64}") }, Optional.empty[EnvUserData]() ), @@ -171,7 +190,6 @@ object HeaderFunctions { returns: Array[LibExtism.ExtismVal], data: Optional[EnvUserData] ) => { - println("calling get header values") returns(0).v.i64 = state.getHeaderValues(plugin, getCurrentVmData(), HeaderKind.fromValue(params(0).v.i32), params(1).v.i32, @@ -191,7 +209,6 @@ object HeaderFunctions { returns: Array[LibExtism.ExtismVal], data: Optional[EnvUserData] ) => { - println("SET HEADER VALUE") state.setHeader(plugin, getCurrentVmData(), HeaderKind.fromValue(params(0).v.i32), params(1).v.i32, params(2).v.i32, params(3).v.i32, params(4).v.i32) }, Optional.empty[EnvUserData]() @@ -206,7 +223,6 @@ object HeaderFunctions { returns: Array[LibExtism.ExtismVal], data: Optional[EnvUserData] ) => { - println("ADD HEADER VALUE") state.addHeader(plugin, getCurrentVmData(), HeaderKind.fromValue(params(0).v.i32), params(1).v.i32, params(2).v.i32, params(3).v.i32, params(4).v.i32) }, Optional.empty[EnvUserData]() @@ -272,7 +288,9 @@ object RequestFunctions { params: Array[LibExtism.ExtismVal], returns: Array[LibExtism.ExtismVal], data: Optional[EnvUserData] - ) => returns(0).v.i32 = state.getMethod(plugin, getCurrentVmData(), params(0).v.i32, params(1).v.i32), + ) => { + returns(0).v.i32 = state.getMethod(plugin, getCurrentVmData(), params(0).v.i32, params(1).v.i32) + }, Optional.empty[EnvUserData]() ), new HostFunction[EnvUserData]( @@ -337,7 +355,7 @@ object RequestFunctions { returns: Array[LibExtism.ExtismVal], data: Optional[EnvUserData] ) => { - println("get_source_addr TODO - not defined") + returns(0).v.i32 = state.getSourceAddr(plugin, getCurrentVmData(), params(0).v.i32, params(1).v.i32) }, Optional.empty[EnvUserData]() ) @@ -391,7 +409,6 @@ object HttpWasmFunctions { Option(vmDataRef.get()) match { case Some(data: HttpWasmVmData) => data case _ => - println("missing vm data") new RuntimeException("missing vm data").printStackTrace() throw new RuntimeException("missing vm data") } diff --git a/otoroshi/app/wasm/httpwasm/httpwasm.scala b/otoroshi/app/wasm/httpwasm/httpwasm.scala index 3fb8b3dd2..7b4653e81 100644 --- a/otoroshi/app/wasm/httpwasm/httpwasm.scala +++ b/otoroshi/app/wasm/httpwasm/httpwasm.scala @@ -8,6 +8,7 @@ import org.extism.sdk.wasmotoroshi._ import org.extism.sdk.{ExtismCurrentPlugin, HostFunction, HostUserData, LibExtism} import otoroshi.env.Env import otoroshi.gateway.Errors +import otoroshi.models.BadResponse import otoroshi.next.plugins.api._ import otoroshi.utils.TypedMap import otoroshi.utils.syntax.implicits._ @@ -17,7 +18,7 @@ import otoroshi.wasm.httpwasm.api.{BodyKind, HeaderKind} import play.api._ import play.api.libs.json._ import play.api.libs.typedmap.TypedKey -import play.api.mvc.Results.{Ok, Status} +import play.api.mvc.Results.{BadRequest, Ok, Status} import play.api.mvc.{RequestHeader, Result, Results} import java.util.Optional @@ -84,6 +85,7 @@ class NgHttpWasm extends NgRequestTransformer { private def handleResponse(vm: WasmVm, vmData: HttpWasmVmData, reqCtx: Int, isError: Int) (implicit env: Env, ec: ExecutionContext) = { + vmData.afterNext = true vm.call( WasmFunctionParameters.NoResult("handle_response", new Parameters(2).pushInts(reqCtx, isError)), vmData.some @@ -96,6 +98,8 @@ class NgHttpWasm extends NgRequestTransformer { .withRequest(ctx.otoroshiRequest) .some + vmData.get.remoteAddress = ctx.request.remoteAddress.some + vm.callWithParamsAndResult("handle_request", new Parameters(0), 1, @@ -115,49 +119,42 @@ class NgHttpWasm extends NgRequestTransformer { ).map(r => Left(r)) } case Right(res) => - val ctxNext = res.results.getValue(0).v.i64 + if (res.results.getLength > 0) { + val ctxNext = res.results.getValue(0).v.i64 - val data = vmData.get - if ((ctxNext & 0x1) != 0x1) { + val data = vmData.get + if ((ctxNext & 0x1) != 0x1) { Left(data.response.asResult).future - } else { - data.nextCalled = true - - val reqCtx = ctxNext >> 32 - handleResponse(vm, data, reqCtx.toInt, 0) - - implicit val mat = env.otoroshiMaterializer + } else { + val reqCtx = ctxNext >> 32 + handleResponse(vm, data, reqCtx.toInt, 0) - if (data.request.hasBody) { Right(ctx.otoroshiRequest.copy( headers = data.request.headers, url = data.request.url, method = data.request.method, body = data.request.body )).future - } else { - Right(ctx.otoroshiRequest.copy( - headers = data.request.headers, - url = data.request.url, - method = data.request.method, - )).future } + } else { + println("missing handle request result") + Left(BadRequest(Json.obj("error" -> "missing handle request result"))).future } } } -// override def transformRequest( -// ctx: NgTransformerRequestContext -// )(implicit env: Env, ec: ExecutionContext, mat: Materializer): -// Future[Either[mvc.Result, NgPluginHttpRequest]] = { -// println("Calling transform request") -// ctx.attrs.get(otoroshi.wasm.httpwasm.HttpWasmPluginKeys.HttpWasmVmKey) match { -// case None => -// println("no vm found in attrs") -// Future.failed(new RuntimeException("no vm found in attrs")) -// case Some(vm) => execute(vm, ctx) -// } -// } + override def transformRequest( + ctx: NgTransformerRequestContext + )(implicit env: Env, ec: ExecutionContext, mat: Materializer): + Future[Either[mvc.Result, NgPluginHttpRequest]] = { + println("Calling transform request") + ctx.attrs.get(otoroshi.wasm.httpwasm.HttpWasmPluginKeys.HttpWasmVmKey) match { + case None => + println("no vm found in attrs") + Future.failed(new RuntimeException("no vm found in attrs")) + case Some(vm) => execute(vm, ctx) + } + } override def afterRequest( ctx: NgAfterRequestContext @@ -166,79 +163,86 @@ class NgHttpWasm extends NgRequestTransformer { ().vfuture } - override def transformResponse( - ctx: NgTransformerResponseContext - )(implicit env: Env, ec: ExecutionContext, mat: Materializer): Future[Either[Result, NgPluginHttpResponse]] = { - ctx.attrs.get(otoroshi.wasm.httpwasm.HttpWasmPluginKeys.HttpWasmVmKey) match { - case None => - println("no vm found in attrs") - Future.failed(new RuntimeException("no vm found in attrs")) - case Some(vm) => - val vmData = HttpWasmVmData - .withRequest(NgPluginHttpRequest( - headers = ctx.otoroshiResponse.headers, - url = ctx.request.uri, - method = ctx.request.method, - version = ctx.request.version, - clientCertificateChain = () => None, - cookies = Seq.empty, - body = Source.empty, - backend = None - )) - vmData.response = vmData.response.copy( - headers = ctx.otoroshiResponse.headers, - status = ctx.otoroshiResponse.status, - cookies = ctx.otoroshiResponse.cookies, - body = ctx.otoroshiResponse.body - ) - - vm.callWithParamsAndResult("handle_request", - new Parameters(0), - 1, - None, - vmData.some - ) - .flatMap { - case Left(error) => { - Errors.craftResponseResult( - error.toString(), - Status(401), - ctx.request, - None, - None, - attrs = TypedMap.empty - ).map(r => Left(r)) - } - case Right(res) => - val ctxNext = res.results.getValue(0).v.i64 - - val data = vmData - if ((ctxNext & 0x1) != 0x1) { - Left(data.response.asResult).future - } else { - data.nextCalled = true - - val reqCtx = ctxNext >> 32 - handleResponse(vm, data, reqCtx.toInt, 0) - - implicit val mat = env.otoroshiMaterializer - - if (data.request.hasBody) { - Right(ctx.otoroshiResponse.copy( - headers = data.response.headers, - status = data.response.status, - cookies = data.response.cookies, - body = data.response.body, - )).future - } else { - Right(ctx.otoroshiResponse.copy( - headers = data.response.headers, - status = data.response.status, - cookies = data.response.cookies - )).future - } - } - } - } - } + // TODO - only useful for testing +// override def transformResponse( +// ctx: NgTransformerResponseContext +// )(implicit env: Env, ec: ExecutionContext, mat: Materializer): Future[Either[Result, NgPluginHttpResponse]] = { +// ctx.attrs.get(otoroshi.wasm.httpwasm.HttpWasmPluginKeys.HttpWasmVmKey) match { +// case None => +// println("no vm found in attrs") +// Future.failed(new RuntimeException("no vm found in attrs")) +// case Some(vm) => +// val vmData = HttpWasmVmData +// .withRequest(NgPluginHttpRequest( +// headers = ctx.otoroshiResponse.headers, +// url = ctx.request.uri, +// method = ctx.request.method, +// version = ctx.request.version, +// clientCertificateChain = () => None, +// cookies = Seq.empty, +// body = Source.empty, +// backend = None +// )) +// vmData.remoteAddress = ctx.request.remoteAddress.some +// vmData.response = vmData.response.copy( +// headers = ctx.otoroshiResponse.headers, +// status = ctx.otoroshiResponse.status, +// cookies = ctx.otoroshiResponse.cookies, +// body = ctx.otoroshiResponse.body +// ) +// +// vm.callWithParamsAndResult("handle_request", +// new Parameters(0), +// 1, +// None, +// vmData.some +// ) +// .flatMap { +// case Left(error) => { +// Errors.craftResponseResult( +// error.toString(), +// Status(401), +// ctx.request, +// None, +// None, +// attrs = TypedMap.empty +// ).map(r => Left(r)) +// } +// case Right(res) => +// if(res.results.getLength() > 0){ +// val ctxNext = res.results.getValue(0).v.i64 +// +// val data = vmData +// if ((ctxNext & 0x1) != 0x1) { +// Left(data.response.asResult).future +// } else { +// data.nextCalled = true +// +// val reqCtx = ctxNext >> 32 +// handleResponse(vm, data, reqCtx.toInt, 0) +// +// implicit val mat = env.otoroshiMaterializer +// +// if (data.request.hasBody) { +// Right(ctx.otoroshiResponse.copy( +// headers = data.response.headers, +// status = data.response.status, +// cookies = data.response.cookies, +// body = data.response.body, +// )).future +// } else { +// Right(ctx.otoroshiResponse.copy( +// headers = data.response.headers, +// status = data.response.status, +// cookies = data.response.cookies +// )).future +// } +// } +// } else { +// println("missing handle request result") +// Left(BadRequest(Json.obj("error" -> "missing handle request result"))).future +// } +// } +// } +// } } \ No newline at end of file diff --git a/otoroshi/app/wasm/httpwasm/RequestState.scala b/otoroshi/app/wasm/httpwasm/utils.scala similarity index 69% rename from otoroshi/app/wasm/httpwasm/RequestState.scala rename to otoroshi/app/wasm/httpwasm/utils.scala index 72c39fe08..87dff432b 100644 --- a/otoroshi/app/wasm/httpwasm/RequestState.scala +++ b/otoroshi/app/wasm/httpwasm/utils.scala @@ -1,9 +1,5 @@ package otoroshi.wasm.httpwasm.api -import org.extism.sdk.HostUserData -import otoroshi.next.plugins.api.{NgPluginHttpRequest, NgPluginHttpResponse} -import otoroshi.utils.syntax.implicits._ - sealed trait HeaderKind { def value: Int } @@ -28,6 +24,7 @@ object HeaderKind { case 1 => HeaderKindResponse case 2 => HeaderKindRequestTrailers case 3 => HeaderKindResponseTrailers + case _ => throw new Exception("invalid header kind") } } } @@ -51,6 +48,14 @@ object BodyKind { case 1 => BodyKindResponse } } + + def toString(value: BodyKind): String = { + value match { + case BodyKindRequest => "BodyKindRequest" + case BodyKindResponse => "BodyKindResponse" + case _ => throw new Exception("invalid body kind") + } + } } sealed trait LogLevel { @@ -85,6 +90,7 @@ object LogLevel { case 1 => LogLevelWarn case 2 => LogLevelError case 3 => LogLevelNone + case _ => throw new Exception("invalid log level") } } } @@ -106,10 +112,24 @@ object Feature { case object FeatureTrailers extends Feature { def value: Int = 1 << 2 } + + def toString(feature: Feature): String = { + feature match { + case FeatureBufferRequest => "FeatureBufferRequest" + case FeatureBufferResponse => "FeatureBufferResponse" + case FeatureTrailers => "FeatureTrailers" + case _ => throw new Exception("invalid feature") + } + } } -case class Features(features: Int) { - def has(feature: Feature): Boolean = { - (features & feature.value) == feature.value +case class Features(f: Int) { + def withEnabled(feature: Int): Features = { + Features(f | feature) + } + + // returns true if the feature (or group of features) is enabled. + def isEnabled(feature: Feature): Boolean = { + (f & feature.value) != 0 } } \ No newline at end of file diff --git a/otoroshi/lib/wasm4s-bundle_2.12-dev.jar b/otoroshi/lib/wasm4s-bundle_2.12-dev.jar index 56241e0e91c46bb43b50a7114281126929176d4c..1c26312a06963173e7d719304fb33feb3d62d3a9 100644 GIT binary patch delta 49088 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 bNmYkNHbI%Q{z^xiX#Hvi)@WU$Mveai6S(kp delta 48373 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