Implementation:Langgenius Dify Fetch Layer
| Knowledge Sources | |
|---|---|
| Domains | Frontend, HTTP Client, Authentication |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
Core HTTP fetch abstraction built on the ky library that provides authenticated, error-handling, CSRF-protected requests for all Dify frontend API calls.
Description
The Fetch Layer is the central HTTP client module for the Dify frontend. It wraps the ky HTTP library with a configurable base function that handles request construction, header management, error handling, and response parsing for three API targets: the console API, the public (web-app) API, and the marketplace API.
Key features include:
- CSRF protection: Automatically reads the CSRF token from cookies and sets it on request headers for non-marketplace calls.
- Public API authentication: For public API requests, it injects the web-app access token (Bearer) and share-code/passport headers via the
beforeRequestPublicWithCodehook. - Error handling: After-response hooks inspect HTTP status codes and display toast notifications for errors. 401 responses are rejected as promises for upstream token-refresh handling. 403 with
already_setupcode redirects to the sign-in page. - 204 normalization: Converts 204 No Content responses into
{ result: 'success' }JSON for consistent downstream handling. - Content-type routing: Automatically returns blobs for binary content types (audio, download, zip) and JSON for everything else.
- Fetch compatibility mode: Supports an
otherOptions.fetchCompatflag for use with the oRPC client, which passes aRequestobject directly rather than constructing one from scratch. - Configurable timeout: Default 100-second timeout on all requests.
Usage
This module is imported as the base function by web/service/base.ts, which re-exports convenience wrappers (get, post, put, del). All service modules throughout the Dify frontend depend on this layer for HTTP communication.
Code Reference
Source Location
- Repository: Langgenius_Dify
- File: web/service/fetch.ts
Signature
export const ContentType: {
json: string
stream: string
audio: string
form: string
download: string
downloadZip: string
upload: string
}
export type FetchOptionType = Omit<RequestInit, 'body'> & {
params?: Record<string, any>
body?: BodyInit | Record<string, any> | null
}
export type ResponseError = {
code: string
message: string
status: number
}
export const getBaseOptions: () => RequestInit
export function base<T>(url: string, options?: FetchOptionType, otherOptions?: IOtherOptions): Promise<T>
Import
import { base, ContentType, getBaseOptions } from '@/service/fetch'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| url | string |
Yes | API endpoint path (relative to the selected base prefix) |
| options | FetchOptionType |
No | Standard fetch options plus params and typed body
|
| otherOptions.isPublicAPI | boolean |
No | Route request through PUBLIC_API_PREFIX with share-code auth |
| otherOptions.isMarketplaceAPI | boolean |
No | Route request through MARKETPLACE_API_PREFIX with omitted credentials |
| otherOptions.bodyStringify | boolean |
No | Whether to JSON-stringify the body (default true) |
| otherOptions.deleteContentType | boolean |
No | Remove Content-Type header (for file uploads) |
| otherOptions.needAllResponseContent | boolean |
No | Return the full Response object instead of parsed content |
| otherOptions.silent | boolean |
No | Suppress error toast notifications |
| otherOptions.getAbortController | (ac: AbortController) => void |
No | Callback to receive the AbortController for cancellation |
| otherOptions.fetchCompat | boolean |
No | oRPC compatibility mode that passes a Request object directly |
Outputs
| Name | Type | Description |
|---|---|---|
| T | generic |
Parsed JSON response, Blob for binary types, or full Response in compat/allContent mode |
Usage Examples
import { base, ContentType } from '@/service/fetch'
// Simple GET request to console API
const data = await base<{ apps: App[] }>('/apps', { method: 'GET' })
// POST with JSON body
const result = await base('/apps', {
method: 'POST',
body: { name: 'My App', mode: 'chat' },
})
// Public API request with share code auth
const appInfo = await base('/app-info', {}, { isPublicAPI: true })
// File upload with deleted content type
const uploadResult = await base('/files/upload', {
method: 'POST',
body: formData,
}, { deleteContentType: true, bodyStringify: false })
Related Pages
- Langgenius_Dify_ORPC_Client - oRPC client that uses fetchCompat mode through this layer
- Langgenius_Dify_Refresh_Token - Token refresh logic triggered by 401 responses from this layer
- Langgenius_Dify_Webapp_Auth - Web app access token and passport management used by public API hooks