How to pass context to vanilla client?
Hi,
I have a next app where I use trpc. Now I need to call some trpc functions from outside of any components. My first solution was to just call the endpoint with axios.
const { data: attribute } = await axios({
method: "GET",
url: getApiServerUrl() + "/trpc/db.getAttribute",
params: {
input: JSON.stringify(trpcInput)
},
headers: { 'Cookie': cookie }
});
This is working fine, but I lose typing support.
My new solution is to use the vanilla client. But using the vanilla client I can't find a way to pass context to the request, for example to pass a cookie. Now my walkaround is creating a getter function that each time creates a new trpc client with the context needed.
export const getClientWithCookie = ({cookie}: {cookie: string}) => createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: getApiServerUrl() +
/trpc,
headers() {
return {
cookie: cookie,
};
},
}),
],
});
const attribute = await getClientWithCookie({cookie: cookie}).db.getAttribute.query(trpcInput);
This is also working fine, but feels a bit hacky to me, because each time it creates a new client.
How would be the proper solution to call a trpc function with context like a cookie using the vanilla client? (I can't use hooks here)16 Replies
I want to revive this because I searched through #❓-help and didn't find any other post answering this. If your server sets Set-Cookie, how do you retrieve that cookie in the Vanilla tRPC client?
From Node.JS clientside I call my login proc, which gives me back a user ID and gives me a session token via Set-Cookie, but I cannot for the life of me figure out how to get that cookie. I've been digging through the docs and the code for hours now.
I think my issue is actually not quite related to OP's issue but you'll forgive me since I have been staring at my screen too long
Cookies are managed by the browser and are sent on subsequent requests to the server, you don’t have to include it yourself
Only when using SSR do you have to pass the cookies to the link
This is NodeJS, not the browser
Node AFAIK does not store the cookie, subsequent requests are met with auth errors
If the node server sets
Set-Cookie
, the browser will automatically add the cookie to the req header on each http calls. I think your question is that your trpc client can't access the req header or the http-only cookies. So my suggestion is that handle the auth event(like validate cookies) through the node middleware, and set something you want to the ctx(like req.trpc.session or ctx.trpc.session), then pass them to trpc context. Make sure the trpc middleware should run after the auth middleware.Again, there is no browser involved here. I am running the vanilla client in NodeJS.
Since the Node.js will not handle the
Set-Cookie
automatically, you should parse the header and save the token manually in the server adapter.Okay, how do I actually get the header? Can I write middleware for the client?
I think you could write a middleware after the trpc adapter, if the res.headers include Set-Cookie it parses the header and saves the cookie somewhere(could be stored at the top level variable I think), and you also need to write another middleware before the trpc adapter, it writes the cookie to the req.headers if the cookie is not null.
Ok, I think my issue here then is documentation. I understand that you can write middleware for the server by calling
.use
on a procedure, but I don't see anything about doing this on the client.
The solution I'm using as of yesterday is to use fetch
to call the login API and save the cookie to a variable, then use the headers
function of the object I pass to httpBatchLink
to set that cookie in subsequent requests' headers (using tRPC for subsequent requests).Hmmm, the middleware I said is the server side not the trpc's.
I think there has to be a miscommunication somewhere lol
Maybe it would be helpful to know that I cannot modify the server? It is running on a website I don't manage. I'm writing a third party API client, I am forced to deal with the Set-Cookie header.
There is a server running NodeJS+tRPC. I am trying to write a different NodeJS package, also using tRPC, for making programmatic API calls to that server. The API server does session tracking using Set-Cookie. The API client, since it is also NodeJS, does not respect the Set-Cookie header (as far as I am aware), so I have to access the header myself to store the cookie in a variable somewhere. My issue is that I cannot figure out how to directly access the request header using @trpc/client.
I am aware that this is probably an uncommon and unsupported use case (specifically the part about this being a 3rd party client), but I still think it highlights either a feature missing from the vanilla client, or, if the feature does exist, it highlights missing documentation for it
I just found this https://trpc.io/docs/client/links/httpBatchLink#httpbatchlink-options
HTTP Batch Link | tRPC
httpBatchLink is a terminating link that batches an array of individual tRPC operations into a single HTTP request that's sent to a single tRPC procedure.
Yes, I'm using this already. I mention it here
Maybe I can supply a custom fetch() that detects set-cookie in the response?
That feels very hacky
Yeah ok that works, it's not really much better than the other solution but at least it consolidates all my API calls to only using tRPC.
I think this is the best way now. 😫
To rewrite the fetch() function