Transport HTTP
Examples -> Abort Custom Fetch Dynamic Headers Headers Method Get Raw
Getting Started
This extension adds an http
transport to your client. It implements the "GraphQL Over HTTP" specification.
This extension is included in presets minimal
and basic
. Therefore we show usage here with the bare
preset which does not include this extension.
import { TransportHttp } from 'graffle/extensions/transport-http'
import { GraffleBare } from 'graffle/presets/bare'
GraffleBare.create().use(TransportHttp).transport({
url: 'https://api.service.io/graphql',
})
Relative URLs
The transport supports relative URLs, which are useful in browser environments and framework integrations.
Note: Node.js's native fetch does not support relative URLs. They only work in:
- Browser environments (where they're resolved against the page origin)
- Frameworks that provide enhanced fetch implementations (like SvelteKit's load function)
Basic Usage
import { TransportHttp } from 'graffle/extensions/transport-http'
import { GraffleBare } from 'graffle/presets/bare'
// Relative paths are supported
GraffleBare.create().use(TransportHttp).transport({
url: '/api/graphql', // Relative to current origin
})
// Also supports parent directory traversal
GraffleBare.create().use(TransportHttp).transport({
url: '../graphql', // Relative to parent directory
})
// And current directory paths
GraffleBare.create().use(TransportHttp).transport({
url: './graphql', // Relative to current directory
})
Framework Integration Example (SvelteKit)
In frameworks like SvelteKit, you can leverage the framework's enhanced fetch that properly handles relative URLs during server-side rendering:
// In a SvelteKit load function
export async function load({ fetch }) {
const client = GraffleBare
.create()
.use(TransportHttp)
.transport({ url: '/api/graphql' })
.anyware(({ exchange }) => {
// Use SvelteKit's enhanced fetch
exchange.fetch = fetch
return exchange()
})
// Client will now use relative URLs with SvelteKit's fetch
const data = await client.gql`{ posts { title } }`.send()
return { posts: data.posts }
}
For more information about URL resolution in browsers, see MDN's documentation on the Fetch API.
Configuration
You can generally configure aspects of the transport in three ways:
- In the constructor under
transport
. - Using
with
undertransport
. - Using extensions.
Graffle
.create()
.transport({
headers: { authorization: '...' },
raw: { mode: 'cors' },
})
Precedence is:
- The extension stack, later extensions taking precedence
with
configuration- Constructor configuration
Within each of the above the raw
configuration takes precedence over other properties directly under transport
.
Note:
- Headers are merged.
- If a header is given an empty string value, then it deletes that header value if previously set.
- Because
transport.raw
has zero guard rails you should know what you're doing when using it. For example if you setraw.method
toPATCH
that would override themethodMode
configuration and lead to a generally invalid GraphQL request over HTTP.
GET
Examples -> Method Get
By default all requests use HTTP POST. However you can configure queries to be sent over HTTP GET.
Graffle
.create()
.transport({
methodMode: 'getReads',
})
POST
By default all requests use HTTP POST. If you need to explicitly re-configure this you can.
Graffle
.create()
.transport({
methodMode: 'post',
})
Anyware
Examples -> Custom Fetch Dynamic Headers
Hooks are augmented in the following ways:
Encode | Pack | Exchange | Unpack | Decode | |
---|---|---|---|---|---|
Input | - | url headers body | request | response | response |
Functions | - | - | fetch |
URL Type in Anyware
The request.url
in the Exchange hook is a discriminated union that preserves whether the URL is a relative path or absolute URL:
.anyware(async ({ exchange }) => {
// Access the discriminated union
if (exchange.input.request.url._tag === 'path') {
// It's a relative path (string)
console.log('Path:', exchange.input.request.url.value)
} else {
// It's an absolute URL (URL object)
console.log('URL:', exchange.input.request.url.value.href)
}
return exchange()
})
Raw
- You can easily pass configuration to
fetch
viatransport.raw
. - It takes precedence over other
transport.*
properties. - Because
transport.raw
has zero guard rails you should know what you're doing when using it. For example if you setraw.method
toPATCH
that would override themethodMode
configuration and lead to a generally invalid GraphQL request over HTTP.
Graffle
.create()
.transport({
raw: { mode: 'cors' },
})