Search code examples
luaprotocol-buffersenvoyproxyopenresty

How to unmarshal protobuf header on envoy


I have a custom header that is marshaled with protobuf (in a lua script inside an openresty plugin), called x-internal-state-bin.

Now I want to have access to this header in an inline lua code on my envoy, how can I unmarshal this custom proto (I have the proto file)? Or if there are other solutions with other filters than lua.


Solution

  • I came up with unmarshalling the proto inside the inline lua code.

    Note that this solution needs lua-protobuf module to unmarshal the proto header and this module is not present in envoy docker image. According to this issue, I changed the docker file and installed this module.

    Dockerfile content:

    FROM docker.io/envoyproxy/envoy-dev:c89cc2ab48769efd726a0db8c8d75d516554a529 # note that this should be the dev tag
    
    RUN apt update && apt install -y \
        luarocks git
    
    RUN luarocks install lua-protobuf
    RUN luarocks install base64
    

    Lua inline code to unmarshal protobuf:

    function envoy_on_request(request_handle)
      local pb = require "pb"
      local protoc = require "protoc"
      local base64 = require "base64"
    
      -- My proto definitioned copied from my .pb file
      assert(protoc:load [[
        syntax = "proto3";
    
        message RequestState {
          repeated int32 ids = 2;
      } ]])
    
      local rawh = request_handle:headers():get("x-state-bin")
      -- Some magics for base64 padding, ignore it
      while (string.len(rawh) % 4 ~= 0) do
        rawh = rawh .. "="
      end
      local bhead = base64.decode(rawh)
      -- RequestState is the name of the proto message that is defined above
      local message = assert(pb.decode("RequestState", bhead))
    
      local ids = table.concat(message.ids, ",")
      request_handle:headers():add("x-ids", "ids-"..ids)
    end