Skip to content

Commit

Permalink
feat: automatically add csrf token in request headers
Browse files Browse the repository at this point in the history
Fix #21
  • Loading branch information
Julien-R44 committed Nov 23, 2024
1 parent 7678e36 commit ab51d40
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
7 changes: 7 additions & 0 deletions .changeset/healthy-coats-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@tuyau/client': minor
---

Now the client will automatically add the CSRF token in the headers of each request when present in the cookies, exactly like Axios does.

Related #21
22 changes: 21 additions & 1 deletion packages/client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ function createProxy(options: {
})
}

/**
* Automatically append the csrf token to the request headers
*/
function appendCsrfToken(request: Request) {
const xCsrfToken = globalThis.document?.cookie
.split('; ')
.find((row) => row.startsWith('XSRF-TOKEN='))
.split('=')[1]

request.headers.set('X-XSRF-TOKEN', decodeURIComponent(xCsrfToken))
}

/**
* Create a new Tuyau client
*/
Expand All @@ -76,7 +88,15 @@ export function createTuyau<const Api extends ApiDefinition>(
? TuyauClient<Api['definition'], Api['routes']>
: TuyauRpcClient<Api['definition']> {
const baseUrl = options.baseUrl
const client = ky.create({ prefixUrl: baseUrl, throwHttpErrors: false, ...options })
const client = ky.create({
prefixUrl: baseUrl,
throwHttpErrors: false,
...options,
hooks: {
...options.hooks,
beforeRequest: [...(options.hooks?.beforeRequest || []), appendCsrfToken],
},
})

return createProxy({ client, baseUrl, config: options })
}
25 changes: 25 additions & 0 deletions packages/client/tests/client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,4 +578,29 @@ test.group('Client | Runtime', () => {
},
})
})

test('automatically pickup cookie x-csrf-token', async () => {
// @ts-ignore osef
globalThis.document ||= {}
globalThis.document.cookie = 'XSRF-TOKEN=123'

const tuyau = createTuyau<{
routes: []
definition: {
users: {
$get: {
request: any
response: { 200: Simplify<Serialize<{ token: string }>> }
}
}
}
}>({ baseUrl: 'http://localhost:3333' })

nock('http://localhost:3333')
.get('/users')
.reply(200, { token: '123' })
.matchHeader('X-XSRF-TOKEN', '123')

await tuyau.users.$get()
})
})

0 comments on commit ab51d40

Please sign in to comment.