wa-lang.org/wazero@v1.0.2/imports/proxywasm/hostcall.go (about)

     1  // Copyright 2020-2021 Tetrate
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package proxywasm
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"math"
    21  
    22  	"wa-lang.org/wazero/imports/proxywasm/internal"
    23  	"wa-lang.org/wazero/imports/proxywasm/types"
    24  )
    25  
    26  // GetVMConfiguration is used for retrieving configurations given in the "vm_config.configuration" field.
    27  // This hostcall is only available during types.PluginContext.OnVMStart call.
    28  func GetVMConfiguration() ([]byte, error) {
    29  	return getBuffer(internal.BufferTypeVMConfiguration, 0, math.MaxInt32)
    30  }
    31  
    32  // GetPluginConfiguration is used for retrieving configurations given in the "config.configuration" field.
    33  // This hostcall is only available during types.PluginContext.OnPluginStart call.
    34  func GetPluginConfiguration() ([]byte, error) {
    35  	return getBuffer(internal.BufferTypePluginConfiguration, 0, math.MaxInt32)
    36  }
    37  
    38  // SetTickPeriodMilliSeconds sets the tick interval of types.PluginContext.OnTick calls.
    39  // Only available for types.PluginContext.
    40  func SetTickPeriodMilliSeconds(millSec uint32) error {
    41  	return internal.StatusToError(internal.ProxySetTickPeriodMilliseconds(millSec))
    42  }
    43  
    44  // SetEffectiveContext sets the effective context to "context_id".
    45  // This hostcall is usually used to change the context after receiving
    46  // types.PluginContext.OnQueueReady or types.PluginContext.OnTick
    47  func SetEffectiveContext(contextID uint32) error {
    48  	return internal.StatusToError(internal.ProxySetEffectiveContext(contextID))
    49  }
    50  
    51  // RegisterSharedQueue registers the shared queue on this plugin context.
    52  // "Register" means that OnQueueReady is called for this plugin context whenever a new item is enqueued on that queueID.
    53  // Only available for types.PluginContext. The returned queueID can be used for Enqueue/DequeueSharedQueue.
    54  // Note that "name" must be unique across all Wasm VMs which share the same "vm_id".
    55  // That means you can use "vm_id" to separate shared queue namespace.
    56  func RegisterSharedQueue(name string) (queueID uint32, err error) {
    57  	ptr := internal.StringBytePtr(name)
    58  	st := internal.ProxyRegisterSharedQueue(ptr, len(name), &queueID)
    59  	return queueID, internal.StatusToError(st)
    60  }
    61  
    62  // ResolveSharedQueue acquires the queueID for the given vmID and queueName.
    63  // The returned queueID can be used for Enqueue/DequeueSharedQueue.
    64  func ResolveSharedQueue(vmID, queueName string) (queueID uint32, err error) {
    65  	var ret uint32
    66  	st := internal.ProxyResolveSharedQueue(internal.StringBytePtr(vmID),
    67  		len(vmID), internal.StringBytePtr(queueName), len(queueName), &ret)
    68  	return ret, internal.StatusToError(st)
    69  }
    70  
    71  // EnqueueSharedQueue enqueues data to the shared queue of the given queueID.
    72  // In order to get queue id for a target queue, use "ResolveSharedQueue" first.
    73  func EnqueueSharedQueue(queueID uint32, data []byte) error {
    74  	return internal.StatusToError(internal.ProxyEnqueueSharedQueue(queueID, &data[0], len(data)))
    75  }
    76  
    77  // DequeueSharedQueue dequeues data from the shared queue of the given queueID.
    78  // In order to get queue id for a target queue, use "ResolveSharedQueue" first.
    79  func DequeueSharedQueue(queueID uint32) ([]byte, error) {
    80  	var raw *byte
    81  	var size int
    82  	st := internal.ProxyDequeueSharedQueue(queueID, &raw, &size)
    83  	if st != internal.StatusOK {
    84  		return nil, internal.StatusToError(st)
    85  	}
    86  	return internal.RawBytePtrToByteSlice(raw, size), nil
    87  }
    88  
    89  // PluginDone must be called when OnPluginDone returns false indicating that the plugin is in pending state
    90  // right before deletion by the hosts. Only available for types.PluginContext.
    91  func PluginDone() {
    92  	internal.ProxyDone()
    93  }
    94  
    95  // DispatchHttpCall is for dispatching HTTP calls to a remote cluster. This can be used by all contexts
    96  // including Tcp and Root contexts. "cluster" arg specifies the remote cluster the host will send
    97  // the request against with "headers", "body", and "trailers" arguments. "callBack" function is called if the host successfully
    98  // made the request and received the response from the remote cluster.
    99  // When the callBack function is called, the "GetHttpCallResponseHeaders", "GetHttpCallResponseBody", "GetHttpCallResponseTrailers"
   100  // calls are available for accessing the response information.
   101  func DispatchHttpCall(
   102  	cluster string,
   103  	headers [][2]string,
   104  	body []byte,
   105  	trailers [][2]string,
   106  	timeoutMillisecond uint32,
   107  	callBack func(numHeaders, bodySize, numTrailers int),
   108  ) (calloutID uint32, err error) {
   109  	shs := internal.SerializeMap(headers)
   110  	hp := &shs[0]
   111  	hl := len(shs)
   112  
   113  	sts := internal.SerializeMap(trailers)
   114  	tp := &sts[0]
   115  	tl := len(sts)
   116  
   117  	var bodyPtr *byte
   118  	if len(body) > 0 {
   119  		bodyPtr = &body[0]
   120  	}
   121  
   122  	u := internal.StringBytePtr(cluster)
   123  	switch st := internal.ProxyHttpCall(u, len(cluster),
   124  		hp, hl, bodyPtr, len(body), tp, tl, timeoutMillisecond, &calloutID); st {
   125  	case internal.StatusOK:
   126  		internal.RegisterHttpCallout(calloutID, callBack)
   127  		return calloutID, nil
   128  	default:
   129  		return 0, internal.StatusToError(st)
   130  	}
   131  }
   132  
   133  // GetHttpCallResponseHeaders is used for retrieving HTTP response headers
   134  // returned by a remote cluster in response to the DispatchHttpCall.
   135  // Only available during "callback" function passed to the DispatchHttpCall.
   136  func GetHttpCallResponseHeaders() ([][2]string, error) {
   137  	return getMap(internal.MapTypeHttpCallResponseHeaders)
   138  }
   139  
   140  // GetHttpCallResponseBody is used for retrieving HTTP response body
   141  // returned by a remote cluster in response to the DispatchHttpCall.
   142  // Only available during "callback" function passed to the DispatchHttpCall.
   143  func GetHttpCallResponseBody(start, maxSize int) ([]byte, error) {
   144  	return getBuffer(internal.BufferTypeHttpCallResponseBody, start, maxSize)
   145  }
   146  
   147  // GetHttpCallResponseTrailers is used for retrieving HTTP response trailers
   148  // returned by a remote cluster in response to the DispatchHttpCall.
   149  // Only available during "callback" function passed to DispatchHttpCall.
   150  func GetHttpCallResponseTrailers() ([][2]string, error) {
   151  	return getMap(internal.MapTypeHttpCallResponseTrailers)
   152  }
   153  
   154  // GetDownstreamData can be used for retrieving TCP downstream data buffered in the host.
   155  // Returned bytes beginning from "start" to "start" + "maxSize" in the buffer.
   156  // Only available during types.TcpContext.OnDownstreamData.
   157  func GetDownstreamData(start, maxSize int) ([]byte, error) {
   158  	return getBuffer(internal.BufferTypeDownstreamData, start, maxSize)
   159  }
   160  
   161  // AppendDownstreamData appends the given bytes to the downstream TCP data buffered in the host.
   162  // Only available during types.TcpContext.OnDownstreamData.
   163  func AppendDownstreamData(data []byte) error {
   164  	return appendToBuffer(internal.BufferTypeDownstreamData, data)
   165  }
   166  
   167  // PrependDownstreamData prepends the given bytes to the downstream TCP data buffered in the host.
   168  // Only available during types.TcpContext.OnDownstreamData.
   169  func PrependDownstreamData(data []byte) error {
   170  	return prependToBuffer(internal.BufferTypeDownstreamData, data)
   171  }
   172  
   173  // ReplaceDownstreamData replaces the downstream TCP data buffered in the host
   174  // with the given bytes. Only available during types.TcpContext.OnDownstreamData.
   175  func ReplaceDownstreamData(data []byte) error {
   176  	return replaceBuffer(internal.BufferTypeDownstreamData, data)
   177  }
   178  
   179  // GetUpstreamData can be used for retrieving upstream TCP data buffered in the host.
   180  // Returned bytes beginning from "start" to "start" + "maxSize" in the buffer.
   181  // Only available during types.TcpContext.OnUpstreamData.
   182  func GetUpstreamData(start, maxSize int) ([]byte, error) {
   183  	return getBuffer(internal.BufferTypeUpstreamData, start, maxSize)
   184  }
   185  
   186  // AppendUpstreamData appends the given bytes to the upstream TCP data buffered in the host.
   187  // Only available during types.TcpContext.OnUpstreamData.
   188  func AppendUpstreamData(data []byte) error {
   189  	return appendToBuffer(internal.BufferTypeUpstreamData, data)
   190  }
   191  
   192  // PrependUpstreamData prepends the given bytes to the upstream TCP data buffered in the host.
   193  // Only available during types.TcpContext.OnUpstreamData.
   194  func PrependUpstreamData(data []byte) error {
   195  	return prependToBuffer(internal.BufferTypeUpstreamData, data)
   196  }
   197  
   198  // ReplaceUpstreamData replaces the upstream TCP data buffered in the host
   199  // with the given bytes. Only available during types.TcpContext.OnUpstreamData.
   200  func ReplaceUpstreamData(data []byte) error {
   201  	return replaceBuffer(internal.BufferTypeUpstreamData, data)
   202  }
   203  
   204  // ContinueTcpStream continues interating on the TCP connection
   205  // after types.Action.Pause was returned by types.TcpContext.
   206  // Only available for types.TcpContext.
   207  func ContinueTcpStream() error {
   208  	// Note that internal.ProxyContinueStream is not implemented in Envoy,
   209  	// so we intentionally choose to pass StreamTypeDownstream here while
   210  	// the name itself is not indicating "continue downstream".
   211  	return internal.StatusToError(internal.ProxyContinueStream(internal.StreamTypeDownstream))
   212  }
   213  
   214  // CloseDownstream closes the downstream TCP connection for this Tcp context.
   215  // Only available for types.TcpContext.
   216  func CloseDownstream() error {
   217  	return internal.StatusToError(internal.ProxyCloseStream(internal.StreamTypeDownstream))
   218  }
   219  
   220  // CloseUpstream closes the upstream TCP connection for this Tcp context.
   221  // Only available for types.TcpContext.
   222  func CloseUpstream() error {
   223  	return internal.StatusToError(internal.ProxyCloseStream(internal.StreamTypeUpstream))
   224  }
   225  
   226  // GetHttpRequestHeaders is used for retrieving HTTP request headers.
   227  // Only available during types.HttpContext.OnHttpRequestHeaders and
   228  // types.HttpContext.OnHttpStreamDone.
   229  func GetHttpRequestHeaders() ([][2]string, error) {
   230  	return getMap(internal.MapTypeHttpRequestHeaders)
   231  }
   232  
   233  // ReplaceHttpRequestHeaders is used for replacing HTTP request headers
   234  // with given headers. Only available during
   235  // types.HttpContext.OnHttpRequestHeaders.
   236  func ReplaceHttpRequestHeaders(headers [][2]string) error {
   237  	return setMap(internal.MapTypeHttpRequestHeaders, headers)
   238  }
   239  
   240  // GetHttpRequestHeader is used for retrieving an HTTP request header value
   241  // for given "key". Only available during types.HttpContext.OnHttpRequestHeaders and
   242  // types.HttpContext.OnHttpStreamDone.
   243  // If multiple values are present for the key, the "first" value found in the host is returned.
   244  // See https://github.com/envoyproxy/envoy/blob/72bf41fb0ecc039f196be02f534bfc2c9c69f348/source/extensions/common/wasm/context.cc#L762-L763
   245  // for detail.
   246  func GetHttpRequestHeader(key string) (string, error) {
   247  	return getMapValue(internal.MapTypeHttpRequestHeaders, key)
   248  }
   249  
   250  // RemoveHttpRequestHeader is used for removing an HTTP request header with
   251  // a given "key". Only available during types.HttpContext.OnHttpRequestHeaders.
   252  func RemoveHttpRequestHeader(key string) error {
   253  	return removeMapValue(internal.MapTypeHttpRequestHeaders, key)
   254  }
   255  
   256  // ReplaceHttpRequestHeader replaces a value for given "key" from request headers.
   257  // Only available during types.HttpContext.OnHttpRequestHeaders.
   258  // If multiple values are present for the key, only the "first" value in the host is replaced.
   259  // See https://github.com/envoyproxy/envoy/blob/72bf41fb0ecc039f196be02f534bfc2c9c69f348/envoy/http/header_map.h#L547-L549
   260  // for detail.
   261  func ReplaceHttpRequestHeader(key, value string) error {
   262  	return replaceMapValue(internal.MapTypeHttpRequestHeaders, key, value)
   263  }
   264  
   265  // AddHttpRequestHeader adds a value for given "key" to the request headers.
   266  // Only available during types.HttpContext.OnHttpRequestHeaders.
   267  func AddHttpRequestHeader(key, value string) error {
   268  	return addMapValue(internal.MapTypeHttpRequestHeaders, key, value)
   269  }
   270  
   271  // GetHttpRequestBody is used for retrieving the entire HTTP request body.
   272  // Only available during types.HttpContext.OnHttpRequestBody.
   273  func GetHttpRequestBody(start, maxSize int) ([]byte, error) {
   274  	return getBuffer(internal.BufferTypeHttpRequestBody, start, maxSize)
   275  }
   276  
   277  // AppendHttpRequestBody appends the given bytes to the HTTP request body buffer.
   278  // Only available during types.HttpContext.OnHttpRequestBody.
   279  // Please note that you must remove the "content-length" header during OnHttpRequestHeaders.
   280  // Otherwise, the wrong content-length is sent to the upstream and that might result in a client crash.
   281  func AppendHttpRequestBody(data []byte) error {
   282  	return appendToBuffer(internal.BufferTypeHttpRequestBody, data)
   283  }
   284  
   285  // PrependHttpRequestBody prepends the given bytes to the HTTP request body buffer.
   286  // Only available during types.HttpContext.OnHttpRequestBody.
   287  // Please note that you must remove the "content-length" header during OnHttpRequestHeaders.
   288  // Otherwise, the wrong content-length is sent to the upstream and that might result in client crash.
   289  func PrependHttpRequestBody(data []byte) error {
   290  	return prependToBuffer(internal.BufferTypeHttpRequestBody, data)
   291  }
   292  
   293  // ReplaceHttpRequestBody replaces the HTTP request body buffer with the given bytes.
   294  // Only available during types.HttpContext.OnHttpRequestBody.
   295  // Please note that you must remove the "content-length" header during OnHttpRequestHeaders.
   296  // Otherwise, the wrong content-length is sent to the upstream and that might result in client crash,
   297  // if the size of the data differs from the original size.
   298  func ReplaceHttpRequestBody(data []byte) error {
   299  	return replaceBuffer(internal.BufferTypeHttpRequestBody, data)
   300  }
   301  
   302  // GetHttpRequestTrailers is used for retrieving HTTP request trailers.
   303  // Only available during types.HttpContext.OnHttpRequestTrailers and
   304  // types.HttpContext.OnHttpStreamDone.
   305  func GetHttpRequestTrailers() ([][2]string, error) {
   306  	return getMap(internal.MapTypeHttpRequestTrailers)
   307  }
   308  
   309  // ReplaceHttpRequestTrailers is used for replacing HTTP request trailers
   310  // with given trailers. Only available during
   311  // types.HttpContext.OnHttpRequestTrailers.
   312  func ReplaceHttpRequestTrailers(trailers [][2]string) error {
   313  	return setMap(internal.MapTypeHttpRequestTrailers, trailers)
   314  }
   315  
   316  // GetHttpRequestTrailer is used for retrieving HTTP request trailer value
   317  // for given "key". Only available during types.HttpContext.OnHttpRequestTrailers and
   318  // types.HttpContext.OnHttpStreamDone.
   319  // If multiple values are present for the key, the "first" value found in the host is returned.
   320  // See https://github.com/envoyproxy/envoy/blob/72bf41fb0ecc039f196be02f534bfc2c9c69f348/source/extensions/common/wasm/context.cc#L762-L763
   321  // for detail.
   322  func GetHttpRequestTrailer(key string) (string, error) {
   323  	return getMapValue(internal.MapTypeHttpRequestTrailers, key)
   324  }
   325  
   326  // RemoveHttpRequestTrailer removes all values for given "key" from the request trailers.
   327  // Only available during types.HttpContext.OnHttpRequestTrailers.
   328  func RemoveHttpRequestTrailer(key string) error {
   329  	return removeMapValue(internal.MapTypeHttpRequestTrailers, key)
   330  }
   331  
   332  // ReplaceHttpRequestTrailer replaces a value for given "key" from the request trailers.
   333  // Only available during types.HttpContext.OnHttpRequestTrailers.
   334  // If multiple values are present for the key, only the "first" value in the host is replaced.
   335  // See https://github.com/envoyproxy/envoy/blob/72bf41fb0ecc039f196be02f534bfc2c9c69f348/envoy/http/header_map.h#L547-L549
   336  // for detail.
   337  func ReplaceHttpRequestTrailer(key, value string) error {
   338  	return replaceMapValue(internal.MapTypeHttpRequestTrailers, key, value)
   339  }
   340  
   341  // AddHttpRequestTrailer adds a value for given "key" to the request trailers.
   342  // Only available during types.HttpContext.OnHttpRequestTrailers.
   343  func AddHttpRequestTrailer(key, value string) error {
   344  	return addMapValue(internal.MapTypeHttpRequestTrailers, key, value)
   345  }
   346  
   347  // ResumeHttpRequest can be used for resuming HTTP request processing that was stopped
   348  // after returning the types.Action.Pause. Only available during types.HttpContext.
   349  func ResumeHttpRequest() error {
   350  	return internal.StatusToError(internal.ProxyContinueStream(internal.StreamTypeRequest))
   351  }
   352  
   353  // GetHttpResponseHeaders is used for retrieving HTTP response headers.
   354  // Only available during types.HttpContext.OnHttpResponseHeaders and
   355  // types.HttpContext.OnHttpStreamDone.
   356  func GetHttpResponseHeaders() ([][2]string, error) {
   357  	return getMap(internal.MapTypeHttpResponseHeaders)
   358  }
   359  
   360  // ReplaceHttpResponseHeaders is used for replacing HTTP response headers
   361  // with given headers. Only available during
   362  // types.HttpContext.OnHttpResponseHeaders.
   363  func ReplaceHttpResponseHeaders(headers [][2]string) error {
   364  	return setMap(internal.MapTypeHttpResponseHeaders, headers)
   365  }
   366  
   367  // GetHttpResponseHeader is used for retrieving an HTTP response header value
   368  // for a given "key". Only available during types.HttpContext.OnHttpResponseHeaders and
   369  // types.HttpContext.OnHttpStreamDone.
   370  // If multiple values are present for the key, the "first" value found in the host is returned.
   371  // See https://github.com/envoyproxy/envoy/blob/72bf41fb0ecc039f196be02f534bfc2c9c69f348/source/extensions/common/wasm/context.cc#L762-L763
   372  // for detail.
   373  func GetHttpResponseHeader(key string) (string, error) {
   374  	return getMapValue(internal.MapTypeHttpResponseHeaders, key)
   375  }
   376  
   377  // RemoveHttpResponseHeader removes all values for given "key" from the response headers.
   378  // Only available during types.HttpContext.OnHttpResponseHeaders.
   379  func RemoveHttpResponseHeader(key string) error {
   380  	return removeMapValue(internal.MapTypeHttpResponseHeaders, key)
   381  }
   382  
   383  // ReplaceHttpResponseHeader replaces the value for given "key" from the response headers.
   384  // Only available during types.HttpContext.OnHttpResponseHeaders.
   385  // If multiple values are present for the key, only the "first" value in the host is replaced.
   386  // See https://github.com/envoyproxy/envoy/blob/72bf41fb0ecc039f196be02f534bfc2c9c69f348/envoy/http/header_map.h#L547-L549
   387  // for detail.
   388  func ReplaceHttpResponseHeader(key, value string) error {
   389  	return replaceMapValue(internal.MapTypeHttpResponseHeaders, key, value)
   390  }
   391  
   392  // AddHttpResponseHeader adds a value for a given "key" to the response headers.
   393  // Only available during types.HttpContext.OnHttpResponseHeaders.
   394  func AddHttpResponseHeader(key, value string) error {
   395  	return addMapValue(internal.MapTypeHttpResponseHeaders, key, value)
   396  }
   397  
   398  // GetHttpResponseBody is used for retrieving the entire HTTP response body.
   399  // Only available during types.HttpContext.OnHttpResponseBody.
   400  func GetHttpResponseBody(start, maxSize int) ([]byte, error) {
   401  	return getBuffer(internal.BufferTypeHttpResponseBody, start, maxSize)
   402  }
   403  
   404  // AppendHttpResponseBody appends the given bytes to the HTTP response body buffer.
   405  // Only available during types.HttpContext.OnHttpResponseBody.
   406  // Please note that you must remove the "content-length" header during OnHttpResponseHeaders.
   407  // Otherwise, the wrong content-length is sent to the upstream and that might result in client crash.
   408  func AppendHttpResponseBody(data []byte) error {
   409  	return appendToBuffer(internal.BufferTypeHttpResponseBody, data)
   410  }
   411  
   412  // PrependHttpResponseBody prepends the given bytes to the HTTP response body buffer.
   413  // Only available during types.HttpContext.OnHttpResponseBody.
   414  // Please note that you must remove the "content-length" header during OnHttpResponseHeaders.
   415  // Otherwise, the wrong content-length is sent to the upstream and that might result in client crash.
   416  func PrependHttpResponseBody(data []byte) error {
   417  	return prependToBuffer(internal.BufferTypeHttpResponseBody, data)
   418  }
   419  
   420  // ReplaceHttpResponseBody replaces the http response body buffer with the given bytes.
   421  // Only available during types.HttpContext.OnHttpResponseBody.
   422  // Please note that you must remove "content-length" header during OnHttpResponseHeaders.
   423  // Otherwise, the wrong content-length is sent to the upstream and that might result in client crash
   424  // if the size of the data differs from the original one.
   425  func ReplaceHttpResponseBody(data []byte) error {
   426  	return replaceBuffer(internal.BufferTypeHttpResponseBody, data)
   427  }
   428  
   429  // GetHttpResponseTrailers is used for retrieving HTTP response trailers.
   430  // Only available during types.HttpContext.OnHttpResponseTrailers and
   431  // types.HttpContext.OnHttpStreamDone.
   432  func GetHttpResponseTrailers() ([][2]string, error) {
   433  	return getMap(internal.MapTypeHttpResponseTrailers)
   434  }
   435  
   436  // ReplaceHttpResponseTrailers is used for replacing HTTP response trailers
   437  // with given trailers. Only available during
   438  // types.HttpContext.OnHttpResponseTrailers.
   439  func ReplaceHttpResponseTrailers(trailers [][2]string) error {
   440  	return setMap(internal.MapTypeHttpResponseTrailers, trailers)
   441  }
   442  
   443  // GetHttpResponseTrailer is used for retrieving an HTTP response trailer value
   444  // for a given "key". Only available during types.HttpContext.OnHttpResponseTrailers and
   445  // types.HttpContext.OnHttpStreamDone.
   446  // If multiple values are present for the key, the "first" value found in the host is returned.
   447  // See https://github.com/envoyproxy/envoy/blob/72bf41fb0ecc039f196be02f534bfc2c9c69f348/source/extensions/common/wasm/context.cc#L762-L763
   448  // for detail.
   449  func GetHttpResponseTrailer(key string) (string, error) {
   450  	return getMapValue(internal.MapTypeHttpResponseTrailers, key)
   451  }
   452  
   453  // RemoveHttpResponseTrailer removes all values for given "key" from the response trailers.
   454  // Only available during types.HttpContext.OnHttpResponseTrailers.
   455  func RemoveHttpResponseTrailer(key string) error {
   456  	return removeMapValue(internal.MapTypeHttpResponseTrailers, key)
   457  }
   458  
   459  // ReplaceHttpResponseTrailer replaces a value for given "key" from the response trailers.
   460  // Only available during types.HttpContext.OnHttpResponseHeaders.
   461  // If multiple values are present for the key, only the "first" value in the host is replaced.
   462  // See https://github.com/envoyproxy/envoy/blob/72bf41fb0ecc039f196be02f534bfc2c9c69f348/envoy/http/header_map.h#L547-L549
   463  // for detail.
   464  func ReplaceHttpResponseTrailer(key, value string) error {
   465  	return replaceMapValue(internal.MapTypeHttpResponseTrailers, key, value)
   466  }
   467  
   468  // AddHttpResponseTrailer adds a value for given "key" to the response trailers.
   469  // Only available during types.HttpContext.OnHttpResponseHeaders.
   470  func AddHttpResponseTrailer(key, value string) error {
   471  	return addMapValue(internal.MapTypeHttpResponseTrailers, key, value)
   472  }
   473  
   474  // ResumeHttpResponse can be used to resume the HTTP response processing that was stopped
   475  // after returning types.Action.Pause. Only available during types.HttpContext.
   476  func ResumeHttpResponse() error {
   477  	return internal.StatusToError(internal.ProxyContinueStream(internal.StreamTypeResponse))
   478  }
   479  
   480  // SendHttpResponse sends an HTTP response to the downstream with given information (headers, statusCode, body).
   481  // The function returns an error if used outside the types.HttpContext.
   482  // You cannot use this call after types.HttpContext.OnHttpResponseHeaders returns
   483  // Continue because the response headers may have already arrived downstream, and
   484  // there is no way to override the headers that were already sent.
   485  // After you've invoked this function, you *must* return types.Action.Pause to
   486  // stop further processing of the initial HTTP request/response.
   487  // Note that the gRPCStatus can be set to -1 if this is a not gRPC stream.
   488  func SendHttpResponse(statusCode uint32, headers [][2]string, body []byte, gRPCStatus int32) error {
   489  	shs := internal.SerializeMap(headers)
   490  	var bp *byte
   491  	if len(body) > 0 {
   492  		bp = &body[0]
   493  	}
   494  	hp := &shs[0]
   495  	hl := len(shs)
   496  	return internal.StatusToError(
   497  		internal.ProxySendLocalResponse(
   498  			statusCode, nil, 0,
   499  			bp, len(body), hp, hl, gRPCStatus,
   500  		),
   501  	)
   502  }
   503  
   504  // GetSharedData is used for retrieving the value for given "key".
   505  // For thread-safe updates you must use the returned "cas" value
   506  // when calling SetSharedData for the same key.
   507  func GetSharedData(key string) (value []byte, cas uint32, err error) {
   508  	var raw *byte
   509  	var size int
   510  
   511  	st := internal.ProxyGetSharedData(internal.StringBytePtr(key), len(key), &raw, &size, &cas)
   512  	if st != internal.StatusOK {
   513  		return nil, 0, internal.StatusToError(st)
   514  	}
   515  	return internal.RawBytePtrToByteSlice(raw, size), cas, nil
   516  }
   517  
   518  // SetSharedData is used for setting key-value pairs in the shared data storage
   519  // which is defined per "vm_config.vm_id" in the hosts.
   520  // The function returns ErrorStatusCasMismatch when the given CAS value
   521  // doesn't match the current value. The error indicates other Wasm VMs
   522  // have already set a value on the same key, and the current CAS for the key gets incremented.
   523  // Implementing a retry logic to handle this error is recommended.
   524  // Setting the cas value to 0 will never return ErrorStatusCasMismatch,
   525  // and the call will always succeed. However, it is not thread-safe.
   526  // Another VM may have already incremented the value, and the value you
   527  // see is already different from the one stored when you call this function.
   528  func SetSharedData(key string, data []byte, cas uint32) error {
   529  	var dataPtr *byte
   530  	if len(data) > 0 { // Empty data is allowed to set, so we need this check.
   531  		dataPtr = &data[0]
   532  	}
   533  	st := internal.ProxySetSharedData(internal.StringBytePtr(key), len(key), dataPtr, len(data), cas)
   534  	return internal.StatusToError(st)
   535  }
   536  
   537  // GetProperty is used for retrieving property/metadata in the host
   538  // for a given path.
   539  // Available path and properties depend on the host implementation.
   540  // For Envoy, please refer to https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes
   541  //
   542  // Note: if the target property is map-type, use GetPropertyMap instead. This GetProperty returns
   543  // raw un-serialized bytes for such properties. For example, if you have the metadata as
   544  //
   545  //	clusters:
   546  //	- name: web_service
   547  //	  metadata:
   548  //	   filter_metadata:
   549  //	     foo:
   550  //	       my_value: '1234'
   551  //	       my_map:
   552  //	         k1: v1
   553  //	         k2: v2
   554  //
   555  // Then,
   556  //   - use GetPropertyMap for {"cluster_metadata", "filter_metadata", "foo", "my_map"}.
   557  //   - use GetProperty    for {"cluster_metadata", "filter_metadata", "foo", "my_value"}.
   558  //
   559  // Note: you cannot get the raw bytes of protobuf. For example, accessing {"cluster_metadata", "filter_data", "foo"}) doesn't
   560  // return the protobuf bytes, but instead this returns the serialized map of "foo". Therefore, we recommend to access individual
   561  // "leaf" fields (not the middle or top field of metadata) to avoid the need to figure out the (host-dependent) encoding of properties.
   562  func GetProperty(path []string) ([]byte, error) {
   563  	if len(path) == 0 {
   564  		return nil, errors.New("path must not be empty")
   565  	}
   566  	var ret *byte
   567  	var retSize int
   568  	raw := internal.SerializePropertyPath(path)
   569  
   570  	err := internal.StatusToError(internal.ProxyGetProperty(&raw[0], len(raw), &ret, &retSize))
   571  	if err != nil {
   572  		return nil, err
   573  	}
   574  	return internal.RawBytePtrToByteSlice(ret, retSize), nil
   575  }
   576  
   577  // GetPropertyMap is the same as GetProperty but can be used to decode map-typed properties.
   578  // See GetProperty for detail.
   579  //
   580  // Note: this operates under the assumption that the path is encoded as map, therefore this might
   581  // cause panic if it is used on the non-map types.
   582  func GetPropertyMap(path []string) ([][2]string, error) {
   583  	b, err := GetProperty(path)
   584  	if err != nil {
   585  		return nil, err
   586  	}
   587  
   588  	return internal.DeserializeMap(b), nil
   589  }
   590  
   591  // SetProperty is used for setting property/metadata in the host
   592  // for a given path.
   593  // Available path and properties depend on the host implementation.
   594  // For Envoy, please refer to https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes
   595  func SetProperty(path []string, data []byte) error {
   596  	if len(path) == 0 {
   597  		return errors.New("path must not be empty")
   598  	} else if len(data) == 0 {
   599  		return errors.New("data must not be empty")
   600  	}
   601  	raw := internal.SerializePropertyPath(path)
   602  	return internal.StatusToError(internal.ProxySetProperty(
   603  		&raw[0], len(raw), &data[0], len(data),
   604  	))
   605  }
   606  
   607  // CallForeignFunction calls a foreign function of given funcName defined by host implementations.
   608  // Foreign functions are host-specific functions, so please refer to the doc of your host implementation for detail.
   609  func CallForeignFunction(funcName string, param []byte) (ret []byte, err error) {
   610  	f := internal.StringBytePtr(funcName)
   611  
   612  	var returnData *byte
   613  	var returnSize int
   614  
   615  	var paramPtr *byte
   616  	if len(param) != 0 {
   617  		paramPtr = &param[0]
   618  	}
   619  
   620  	switch st := internal.ProxyCallForeignFunction(f, len(funcName), paramPtr, len(param), &returnData, &returnSize); st {
   621  	case internal.StatusOK:
   622  		return internal.RawBytePtrToByteSlice(returnData, returnSize), nil
   623  	default:
   624  		return nil, internal.StatusToError(st)
   625  	}
   626  }
   627  
   628  // LogTrace emits a message as a log with Trace log level.
   629  func LogTrace(msg string) {
   630  	internal.ProxyLog(internal.LogLevelTrace, internal.StringBytePtr(msg), len(msg))
   631  }
   632  
   633  // LogTracef formats according to a format specifier and emits as a log with Trace log level.
   634  //
   635  // Note that not all combinations of format and args are supported by tinygo.
   636  // For example, %v with a map will cause a panic. See
   637  // https://tinygo.org/docs/reference/lang-support/stdlib/#fmt for more
   638  // information.
   639  func LogTracef(format string, args ...interface{}) {
   640  	msg := fmt.Sprintf(format, args...)
   641  	internal.ProxyLog(internal.LogLevelTrace, internal.StringBytePtr(msg), len(msg))
   642  }
   643  
   644  // LogDebug emits a message as a log with Debug log level.
   645  func LogDebug(msg string) {
   646  	internal.ProxyLog(internal.LogLevelDebug, internal.StringBytePtr(msg), len(msg))
   647  }
   648  
   649  // LogDebugf formats according to a format specifier and emits as a log with Debug log level.
   650  //
   651  // Note that not all combinations of format and args are supported by tinygo.
   652  // For example, %v with a map will cause a panic. See
   653  // https://tinygo.org/docs/reference/lang-support/stdlib/#fmt for more
   654  // information.
   655  func LogDebugf(format string, args ...interface{}) {
   656  	msg := fmt.Sprintf(format, args...)
   657  	internal.ProxyLog(internal.LogLevelDebug, internal.StringBytePtr(msg), len(msg))
   658  }
   659  
   660  // LogInfo emits a message as a log with Info log level.
   661  func LogInfo(msg string) {
   662  	internal.ProxyLog(internal.LogLevelInfo, internal.StringBytePtr(msg), len(msg))
   663  }
   664  
   665  // LogInfof formats according to a format specifier and emits as a log with Info log level.
   666  //
   667  // Note that not all combinations of format and args are supported by tinygo.
   668  // For example, %v with a map will cause a panic. See
   669  // https://tinygo.org/docs/reference/lang-support/stdlib/#fmt for more
   670  // information.
   671  func LogInfof(format string, args ...interface{}) {
   672  	msg := fmt.Sprintf(format, args...)
   673  	internal.ProxyLog(internal.LogLevelInfo, internal.StringBytePtr(msg), len(msg))
   674  }
   675  
   676  // LogWarn emits a message as a log with Warn log level.
   677  func LogWarn(msg string) {
   678  	internal.ProxyLog(internal.LogLevelWarn, internal.StringBytePtr(msg), len(msg))
   679  }
   680  
   681  // LogWarnf formats according to a format specifier and emits as a log with Warn log level.
   682  //
   683  // Note that not all combinations of format and args are supported by tinygo.
   684  // For example, %v with a map will cause a panic. See
   685  // https://tinygo.org/docs/reference/lang-support/stdlib/#fmt for more
   686  // information.
   687  func LogWarnf(format string, args ...interface{}) {
   688  	msg := fmt.Sprintf(format, args...)
   689  	internal.ProxyLog(internal.LogLevelWarn, internal.StringBytePtr(msg), len(msg))
   690  }
   691  
   692  // LogError emits a message as a log with Error log level.
   693  func LogError(msg string) {
   694  	internal.ProxyLog(internal.LogLevelError, internal.StringBytePtr(msg), len(msg))
   695  }
   696  
   697  // LogErrorf formats according to a format specifier and emits as a log with Error log level.
   698  //
   699  // Note that not all combinations of format and args are supported by tinygo.
   700  // For example, %v with a map will cause a panic. See
   701  // https://tinygo.org/docs/reference/lang-support/stdlib/#fmt for more
   702  // information.
   703  func LogErrorf(format string, args ...interface{}) {
   704  	msg := fmt.Sprintf(format, args...)
   705  	internal.ProxyLog(internal.LogLevelError, internal.StringBytePtr(msg), len(msg))
   706  }
   707  
   708  // LogCritical emits a message as a log with Critical log level.
   709  func LogCritical(msg string) {
   710  	internal.ProxyLog(internal.LogLevelCritical, internal.StringBytePtr(msg), len(msg))
   711  }
   712  
   713  // LogCriticalf formats according to a format specifier and emits as a log with Critical log level.
   714  //
   715  // Note that not all combinations of format and args are supported by tinygo.
   716  // For example, %v with a map will cause a panic. See
   717  // https://tinygo.org/docs/reference/lang-support/stdlib/#fmt for more
   718  // information.
   719  func LogCriticalf(format string, args ...interface{}) {
   720  	msg := fmt.Sprintf(format, args...)
   721  	internal.ProxyLog(internal.LogLevelCritical, internal.StringBytePtr(msg), len(msg))
   722  }
   723  
   724  type (
   725  	// MetricCounter represents a counter metric.
   726  	// Use DefineCounterMetric for initialization.
   727  	MetricCounter uint32
   728  	// MetricGauge represents a gauge metric.
   729  	// Use DefineGaugeMetric for initialization.
   730  	MetricGauge uint32
   731  	// MetricHistogram represents a histogram metric.
   732  	// Use DefineHistogramMetric for initialization.
   733  	MetricHistogram uint32
   734  )
   735  
   736  // DefineCounterMetric returns MetricCounter for a name.
   737  func DefineCounterMetric(name string) MetricCounter {
   738  	var id uint32
   739  	ptr := internal.StringBytePtr(name)
   740  	st := internal.ProxyDefineMetric(internal.MetricTypeCounter, ptr, len(name), &id)
   741  	if err := internal.StatusToError(st); err != nil {
   742  		panic(fmt.Sprintf("define metric of name %s: %v", name, internal.StatusToError(st)))
   743  	}
   744  	return MetricCounter(id)
   745  }
   746  
   747  // Value returns the current value for this counter.
   748  func (m MetricCounter) Value() uint64 {
   749  	var val uint64
   750  	st := internal.ProxyGetMetric(uint32(m), &val)
   751  	if err := internal.StatusToError(st); err != nil {
   752  		panic(fmt.Sprintf("get metric of  %d: %v", uint32(m), internal.StatusToError(st)))
   753  	}
   754  	return val
   755  }
   756  
   757  // Increment increments the current value by an offset for this counter.
   758  func (m MetricCounter) Increment(offset uint64) {
   759  	if err := internal.StatusToError(internal.ProxyIncrementMetric(uint32(m), int64(offset))); err != nil {
   760  		panic(fmt.Sprintf("increment %d by %d: %v", uint32(m), offset, err))
   761  	}
   762  }
   763  
   764  // DefineCounterMetric returns MetricGauge for a name.
   765  func DefineGaugeMetric(name string) MetricGauge {
   766  	var id uint32
   767  	ptr := internal.StringBytePtr(name)
   768  	st := internal.ProxyDefineMetric(internal.MetricTypeGauge, ptr, len(name), &id)
   769  	if err := internal.StatusToError(st); err != nil {
   770  		panic(fmt.Sprintf("error define metric of name %s: %v", name, internal.StatusToError(st)))
   771  	}
   772  	return MetricGauge(id)
   773  }
   774  
   775  // Value returns the current value for this gauge.
   776  func (m MetricGauge) Value() int64 {
   777  	var val uint64
   778  	if err := internal.StatusToError(internal.ProxyGetMetric(uint32(m), &val)); err != nil {
   779  		panic(fmt.Sprintf("get metric of  %d: %v", uint32(m), err))
   780  	}
   781  	return int64(val)
   782  }
   783  
   784  // Add adds an offset to the current value for this gauge.
   785  func (m MetricGauge) Add(offset int64) {
   786  	if err := internal.StatusToError(internal.ProxyIncrementMetric(uint32(m), offset)); err != nil {
   787  		panic(fmt.Sprintf("error adding %d by %d: %v", uint32(m), offset, err))
   788  	}
   789  }
   790  
   791  // DefineHistogramMetric returns MetricHistogram for a name.
   792  func DefineHistogramMetric(name string) MetricHistogram {
   793  	var id uint32
   794  	ptr := internal.StringBytePtr(name)
   795  	st := internal.ProxyDefineMetric(internal.MetricTypeHistogram, ptr, len(name), &id)
   796  	if err := internal.StatusToError(st); err != nil {
   797  		panic(fmt.Sprintf("error define metric of name %s: %v", name, internal.StatusToError(st)))
   798  	}
   799  	return MetricHistogram(id)
   800  }
   801  
   802  // Value returns the current value for this histogram.
   803  func (m MetricHistogram) Value() uint64 {
   804  	var val uint64
   805  	st := internal.ProxyGetMetric(uint32(m), &val)
   806  	if err := internal.StatusToError(st); err != nil {
   807  		panic(fmt.Sprintf("get metric of  %d: %v", uint32(m), internal.StatusToError(st)))
   808  	}
   809  	return val
   810  }
   811  
   812  // Record records a value for this histogram.
   813  func (m MetricHistogram) Record(value uint64) {
   814  	if err := internal.StatusToError(internal.ProxyRecordMetric(uint32(m), value)); err != nil {
   815  		panic(fmt.Sprintf("error adding %d: %v", uint32(m), err))
   816  	}
   817  }
   818  
   819  func setMap(mapType internal.MapType, headers [][2]string) error {
   820  	shs := internal.SerializeMap(headers)
   821  	hp := &shs[0]
   822  	hl := len(shs)
   823  	return internal.StatusToError(internal.ProxySetHeaderMapPairs(mapType, hp, hl))
   824  }
   825  
   826  func getMapValue(mapType internal.MapType, key string) (string, error) {
   827  	var rvs int
   828  	var raw *byte
   829  	if st := internal.ProxyGetHeaderMapValue(
   830  		mapType, internal.StringBytePtr(key), len(key), &raw, &rvs,
   831  	); st != internal.StatusOK {
   832  		return "", internal.StatusToError(st)
   833  	}
   834  
   835  	ret := internal.RawBytePtrToString(raw, rvs)
   836  	return ret, nil
   837  }
   838  
   839  func removeMapValue(mapType internal.MapType, key string) error {
   840  	return internal.StatusToError(
   841  		internal.ProxyRemoveHeaderMapValue(mapType, internal.StringBytePtr(key), len(key)),
   842  	)
   843  }
   844  
   845  func replaceMapValue(mapType internal.MapType, key, value string) error {
   846  	return internal.StatusToError(
   847  		internal.ProxyReplaceHeaderMapValue(
   848  			mapType, internal.StringBytePtr(key), len(key), internal.StringBytePtr(value), len(value),
   849  		),
   850  	)
   851  }
   852  
   853  func addMapValue(mapType internal.MapType, key, value string) error {
   854  	return internal.StatusToError(
   855  		internal.ProxyAddHeaderMapValue(
   856  			mapType, internal.StringBytePtr(key), len(key), internal.StringBytePtr(value), len(value),
   857  		),
   858  	)
   859  }
   860  
   861  func getMap(mapType internal.MapType) ([][2]string, error) {
   862  	var rvs int
   863  	var raw *byte
   864  
   865  	st := internal.ProxyGetHeaderMapPairs(mapType, &raw, &rvs)
   866  	if st != internal.StatusOK {
   867  		return nil, internal.StatusToError(st)
   868  	} else if raw == nil {
   869  		return nil, types.ErrorStatusNotFound
   870  	}
   871  
   872  	bs := internal.RawBytePtrToByteSlice(raw, rvs)
   873  	return internal.DeserializeMap(bs), nil
   874  }
   875  
   876  func getBuffer(bufType internal.BufferType, start, maxSize int) ([]byte, error) {
   877  	var retData *byte
   878  	var retSize int
   879  	switch st := internal.ProxyGetBufferBytes(bufType, start, maxSize, &retData, &retSize); st {
   880  	case internal.StatusOK:
   881  		if retData == nil {
   882  			return nil, types.ErrorStatusNotFound
   883  		}
   884  		return internal.RawBytePtrToByteSlice(retData, retSize), nil
   885  	default:
   886  		return nil, internal.StatusToError(st)
   887  	}
   888  }
   889  
   890  func appendToBuffer(bufType internal.BufferType, buffer []byte) error {
   891  	var bufferData *byte
   892  	if len(buffer) != 0 {
   893  		bufferData = &buffer[0]
   894  	}
   895  	return internal.StatusToError(internal.ProxySetBufferBytes(bufType, math.MaxInt32, 0, bufferData, len(buffer)))
   896  }
   897  
   898  func prependToBuffer(bufType internal.BufferType, buffer []byte) error {
   899  	var bufferData *byte
   900  	if len(buffer) != 0 {
   901  		bufferData = &buffer[0]
   902  	}
   903  	return internal.StatusToError(internal.ProxySetBufferBytes(bufType, 0, 0, bufferData, len(buffer)))
   904  }
   905  
   906  func replaceBuffer(bufType internal.BufferType, buffer []byte) error {
   907  	var bufferData *byte
   908  	if len(buffer) != 0 {
   909  		bufferData = &buffer[0]
   910  	}
   911  	return internal.StatusToError(
   912  		internal.ProxySetBufferBytes(bufType, 0, math.MaxInt32, bufferData, len(buffer)),
   913  	)
   914  }