protojure / lib

A collection of libraries to support Protojure applications at runtime
https://protojure.readthedocs.io
Apache License 2.0
64 stars 14 forks source link

Support metadata feature in generated clients #39

Open ghaskins opened 4 years ago

ghaskins commented 4 years ago

The core grpc support in protojure has a metadata feature which supports adding custom headers, such as 'authorization'. However, this facility is not exposed up through the generated client code. There are a few ways this may be fixed, but the path of least resistance may be to surface a metadata feature on the grpc/client object itself.

abhi18av commented 2 years ago

Hi @ghaskins , I came across this issue while going through the repo for exactly this point.

In my context, I have the following request working using the grpcurl utility.

grpcurl -rpc-header 'authn-token: TOKEN'  -proto myproto.proto URL myproto_v2.API.GetVersion

However, I haven't been able to get this authn-token passed through to the protojure client - could you please guide me on how to this could be done?

ghaskins commented 2 years ago

Hi there,

Can you show me the trace of how grpcurl -rpc-headers sends its request?

In the meantime, let me show you how we set the “Authorization: Bearer xxx” header:

If you look at the client stubs that get generated, each RPC has an arity-4 variant, like

https://github.com/protojure/lib/blob/master/test/protojure/test/grpc/TestService/client.cljc#L20 https://github.com/protojure/lib/blob/master/test/protojure/test/grpc/TestService/client.cljc#L20

The metadata field can be used to submit custom headers, e.g.

(ClientCloseDetect client {“authorization” (str “Bearer “ jwt)} params reply-ch)

Let me know if that helps you.

On Oct 22, 2021, at 8:24 AM, Abhinav Sharma @.***> wrote:

Hi @ghaskins https://github.com/ghaskins , I came across this issue while going through the repo for exactly this point.

In my context, I have the following request working using the grpcurl https://github.com/fullstorydev/grpcurlutility.

grpcurl -rpc-header 'authn-token: TOKEN' -proto myproto.proto URL myproto_v2.API.GetVersion

However, I haven't been able to get this authn-token passed through to the protojure client - could you please guide me on how to this could be done?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/protojure/lib/issues/39#issuecomment-949582386, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACZUHESAGB732643RMWHBTUIFJZBANCNFSM4KYYM5LA. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

abhi18av commented 2 years ago

Sure @ghaskins , here's the trace for grpcurl request

grpcurl -rpc-header 'authn-token: TOKEN'  -proto myproto.proto URL myproto_v2.API.GetVersion

INFO: 2021/10/22 19:34:08 [core] parsed scheme: ""
INFO: 2021/10/22 19:34:08 [core] scheme "" not registered, fallback to default scheme
INFO: 2021/10/22 19:34:08 [core] ccResolverWrapper: sending update to cc: {[{URL  <nil> 0 <nil>}] <nil> <nil>}
INFO: 2021/10/22 19:34:08 [core] ClientConn switching balancer to "pick_first"
INFO: 2021/10/22 19:34:08 [core] Channel switches to new LB policy "pick_first"
INFO: 2021/10/22 19:34:08 [core] Subchannel Connectivity change to CONNECTING
INFO: 2021/10/22 19:34:08 [core] pickfirstBalancer: UpdateSubConnState: 0xc000424280, {CONNECTING <nil>}
INFO: 2021/10/22 19:34:08 [core] Channel Connectivity change to CONNECTING
INFO: 2021/10/22 19:34:08 [core] Subchannel picks a new address "URL" to connect
INFO: 2021/10/22 19:34:09 [core] Subchannel Connectivity change to READY
INFO: 2021/10/22 19:34:09 [core] pickfirstBalancer: UpdateSubConnState: 0xc000424280, {READY <nil>}
INFO: 2021/10/22 19:34:09 [core] Channel Connectivity change to READY

Resolved method descriptor:
rpc GetVersion ( .google.protobuf.Empty ) returns ( .versionpb_v2.Version );

Request metadata to send:
authn-token: TOKEN

Response headers received:
content-type: application/grpc

Estimated response size: 9 bytes

Response contents:
{
  "major": 2,
  "additional": "-rc.4"
}

Response trailers received:
(empty)
Sent 0 requests and received 1 response
INFO: 2021/10/22 19:34:10 [core] Channel Connectivity change to SHUTDOWN
INFO: 2021/10/22 19:34:10 [core] Subchannel Connectivity change to SHUTDOWN

Okay, I have tried your suggestion but seems like I'm still missing some crucial detail here. I'm sharing the generated client info


(defn GetVersion
  ([client params] (GetVersion client {} params))
  ([client metadata params]
  (let [input (async/chan 1)
        output (async/chan 1)
        desc {:service "versionpb_v2.API"
              :method  "GetVersion"
              :input   {:f com.google.protobuf/new-Empty :ch input}
              :output  {:f versionpb_v2/pb->Version :ch output}
              :metadata metadata}]
    (-> (send-unary-params input params)
        (p/then (fn [_] (invoke-unary client desc output)))))))

And in my case, it is a 3-arity function, which I'm invoking like this

@(version-client/GetVersion client {"authn-token:" "TOKEN"} {})

This raises the following error

   clojure.lang.ExceptionInfo: bad status response {:response
   #function[protojure.internal.grpc.client.providers.http2.core/receive-headers/fn--12545]}

    CompletableFuture.java:  395  java.util.concurrent.CompletableFuture/reportGet
    CompletableFuture.java: 1999  java.util.concurrent.CompletableFuture/get
                  core.clj: 2304  clojure.core/deref-future
                  core.clj: 2324  clojure.core/deref
                  core.clj: 2310  clojure.core/deref
                      REPL:    0  net.clojars.biosharp.protobuf.version/eval17544
                      REPL:   -1  net.clojars.biosharp.protobuf.version/eval17544
             Compiler.java: 7181  clojure.lang.Compiler/eval
             Compiler.java: 7136  clojure.lang.Compiler/eval
                  core.clj: 3202  clojure.core/eval
                  core.clj: 3198  clojure.core/eval
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 1977  clojure.core/with-bindings*
                  core.clj: 1977  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  437  clojure.main/repl/read-eval-print/fn
                  main.clj:  437  clojure.main/repl/read-eval-print
                  main.clj:  458  clojure.main/repl/fn
                  main.clj:  458  clojure.main/repl
                  main.clj:  368  clojure.main/repl
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  152  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  218  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  217  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  834  java.lang.Thread/run
ghaskins commented 2 years ago

The arity-3 is normal for a unary function, arity-4 is for streaming. Sorry for the confusion

As to your problem, try removing the colon, eg. @(version-client/GetVersion client {"authn-token" "TOKEN"} {}) I’m not sure if that would cause an exception but it strikes me as incorrect.

On Oct 22, 2021, at 1:51 PM, Abhinav Sharma @.***> wrote:

Sure @ghaskins https://github.com/ghaskins , here's the trace for grpcurl request

grpcurl -rpc-header 'authn-token: TOKEN' -proto myproto.proto URL myproto_v2.API.GetVersion

INFO: 2021/10/22 19:34:08 [core] parsed scheme: "" INFO: 2021/10/22 19:34:08 [core] scheme "" not registered, fallback to default scheme INFO: 2021/10/22 19:34:08 [core] ccResolverWrapper: sending update to cc: {[{URL 0 }] } INFO: 2021/10/22 19:34:08 [core] ClientConn switching balancer to "pick_first" INFO: 2021/10/22 19:34:08 [core] Channel switches to new LB policy "pick_first" INFO: 2021/10/22 19:34:08 [core] Subchannel Connectivity change to CONNECTING INFO: 2021/10/22 19:34:08 [core] pickfirstBalancer: UpdateSubConnState: 0xc000424280, {CONNECTING } INFO: 2021/10/22 19:34:08 [core] Channel Connectivity change to CONNECTING INFO: 2021/10/22 19:34:08 [core] Subchannel picks a new address "URL" to connect INFO: 2021/10/22 19:34:09 [core] Subchannel Connectivity change to READY INFO: 2021/10/22 19:34:09 [core] pickfirstBalancer: UpdateSubConnState: 0xc000424280, {READY } INFO: 2021/10/22 19:34:09 [core] Channel Connectivity change to READY

Resolved method descriptor: rpc GetVersion ( .google.protobuf.Empty ) returns ( .versionpb_v2.Version );

Request metadata to send: authn-token: TOKEN

Response headers received: content-type: application/grpc

Estimated response size: 9 bytes

Response contents: { "major": 2, "additional": "-rc.4" }

Response trailers received: (empty) Sent 0 requests and received 1 response INFO: 2021/10/22 19:34:10 [core] Channel Connectivity change to SHUTDOWN INFO: 2021/10/22 19:34:10 [core] Subchannel Connectivity change to SHUTDOWN

Okay, I have tried your suggestion but seems like I'm still missing some crucial detail here. I'm sharing the generated client info

(defn GetVersion ([client params] (GetVersion client {} params)) ([client metadata params] (let [input (async/chan 1) output (async/chan 1) desc {:service "versionpb_v2.API" :method "GetVersion" :input {:f com.google.protobuf/new-Empty :ch input} :output {:f versionpbv2/pb->Version :ch output} :metadata metadata}] (-> (send-unary-params input params) (p/then (fn [] (invoke-unary client desc output)))))))

And in my case, it is a 3-arity function, which I'm invoking like this

@(version-client/GetVersion client {"authn-token:" "TOKEN"} {}) This raises the following error

clojure.lang.ExceptionInfo: bad status response {:response

function[protojure.internal.grpc.client.providers.http2.core/receive-headers/fn--12545]}

CompletableFuture.java:  395  java.util.concurrent.CompletableFuture/reportGet
CompletableFuture.java: 1999  java.util.concurrent.CompletableFuture/get
              core.clj: 2304  clojure.core/deref-future
              core.clj: 2324  clojure.core/deref
              core.clj: 2310  clojure.core/deref
                  REPL:    0  net.clojars.biosharp.protobuf.version/eval17544
                  REPL:   -1  net.clojars.biosharp.protobuf.version/eval17544
         Compiler.java: 7181  clojure.lang.Compiler/eval
         Compiler.java: 7136  clojure.lang.Compiler/eval
              core.clj: 3202  clojure.core/eval
              core.clj: 3198  clojure.core/eval
interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn/fn
              AFn.java:  152  clojure.lang.AFn/applyToHelper
              AFn.java:  144  clojure.lang.AFn/applyTo
              core.clj:  667  clojure.core/apply
              core.clj: 1977  clojure.core/with-bindings*
              core.clj: 1977  clojure.core/with-bindings*
           RestFn.java:  425  clojure.lang.RestFn/invoke
interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn
              main.clj:  437  clojure.main/repl/read-eval-print/fn
              main.clj:  437  clojure.main/repl/read-eval-print
              main.clj:  458  clojure.main/repl/fn
              main.clj:  458  clojure.main/repl
              main.clj:  368  clojure.main/repl
           RestFn.java: 1523  clojure.lang.RestFn/invoke
interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj:  152  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
              AFn.java:   22  clojure.lang.AFn/run
           session.clj:  218  nrepl.middleware.session/session-exec/main-loop/fn
           session.clj:  217  nrepl.middleware.session/session-exec/main-loop
              AFn.java:   22  clojure.lang.AFn/run
           Thread.java:  834  java.lang.Thread/run

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/protojure/lib/issues/39#issuecomment-949844262, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACZUHACN2HMWH3O5G6C6DLUIGQAZANCNFSM4KYYM5LA. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

abhi18av commented 2 years ago

Thanks for the quick revert Gregory! :)

I tried again after removing the : from the token, however the behavior seems the same as before.