haproxytech / haproxy-lua-oauth

JWT Validation implementation for HAProxy Lua host
Apache License 2.0
105 stars 50 forks source link

H2 response from service #33

Closed Muhammad-1990 closed 1 year ago

Muhammad-1990 commented 1 year ago

Hi, Is it possible to return a h2 response inside 'register_service'?

i have a grpc client calling haproxy that forwards the request to a backend grpc server. all works fine.

if for some reason i want to deny the request, the deny directive doesnt give the grpc client much info what went wrong. how do i provide more info? (currently setting headers in a service)

this doesnot work: http-request deny deny_status 429 content-type text/plain lf-string "too_many_requests" i was hoping i could construct a h2 response from inside a service?

something like...

local protobuf = require('protobuf')
    local input = { code = "403", message = "denied" }
    local message = pb.encode('api.v1.status', input)
    local data = "\x00"..message

applet:add_header("content-type", "application/grpc+proto")
applet:start_response()
applet:send([headers])
applet:send("data ")
NickMRamirez commented 1 year ago

Right, HAProxy currently has limited support for gRPC. It can extract fields from a ProtoBuf message (see the protobuf method and ungrpc method), but it lacks the ability to write ProtoBuf itself. Creating a Lua module to do this, as you're demonstrating, could work. I have no experience doing this, and the haproxy-lua-oauth library here doesn't include any gRPC feature.

I am curious to see how this would work, and I am cheering you on, even though I can't be of immediate help.

In addition to creating an applet, as you're doing, you can also use the new-ish 'reply' function to return a response from a Lua module, without relaying the request to the backend server. There's an example here: https://github.com/haproxytech/haproxy-lua-cors/blob/master/lib/cors.lua#L139

The difference between applet and 'reply' is in where you want to put the "if" statement for whether to deny. With an applet, once the applet is invoked, there's no more option to relay to the server. Therefore, the conditional logic for whether to call it must be in the haproxy.cfg. On the other hand, a 'reply' can exist in a Lua module that contains the conditional logic. So, you might only reply when a condition, defined in Lua code, is met.

Muhammad-1990 commented 1 year ago

Technically I can call an upstream service just to get a formatted error and return that. but it would be too easy and who really wants to deal with another "we dont need more microservices" lecture ... h2 is actually quiet complex... Anywho, here is a very good starting point should anyone come here looking for tips. lukego/grpc_assets.lua

thanks though, guess we can close this off until theres some ground breaking updates...

NickMRamirez commented 1 year ago

Thanks for sharing this @Muhammad-1990 . It's an interesting use case. I will close this issue, but it may be worthwhile to stick your lua file into a repo for others seeking an haproxy-grpc solution.