HTTP-based transport supporting multiple HTTP clients (fetch, axios, superagent) for traditional REST API communication with automatic request/response handling and URL generation.
Create REST transport configuration with support for multiple HTTP client libraries.
/**
* Create REST client configuration
* @param baseURL - Base URL for the API server (optional)
* @returns Object with transport methods for different HTTP clients
*/
function rest(baseURL?: string): {
fetch(connection: any, options?: any): TransportConnection;
axios(connection: any, options?: any): TransportConnection;
superagent(connection: any, options?: any): TransportConnection;
};
interface TransportConnection<Services = any> {
(app: Application): void;
}Usage Examples:
import feathers from "@feathersjs/client";
import { rest } from "@feathersjs/client";
const app = feathers();
// Configure with base URL
const restClient = rest("http://localhost:3030");
// Use with different HTTP clients
app.configure(restClient.fetch(fetch));
// OR
app.configure(restClient.axios(axios));
// OR
app.configure(restClient.superagent(superagent));Configure REST transport using the Fetch API (browser native or node-fetch).
/**
* Configure Fetch API transport
* @param connection - Fetch function (global fetch or node-fetch)
* @param options - Optional fetch configuration
* @returns Transport connection function
*/
fetch(connection: any, options?: any): TransportConnection;Usage Examples:
// Browser environment (global fetch)
app.configure(rest("https://api.example.com").fetch(fetch));
// Node.js environment with node-fetch
import fetch from "node-fetch";
app.configure(rest("https://api.example.com").fetch(fetch));
// With custom options
app.configure(rest("https://api.example.com").fetch(fetch, {
headers: {
"User-Agent": "MyApp/1.0"
},
timeout: 10000
}));Configure REST transport using Axios HTTP client library.
/**
* Configure Axios transport
* @param connection - Axios instance or axios function
* @param options - Optional axios configuration
* @returns Transport connection function
*/
axios(connection: any, options?: any): TransportConnection;Usage Examples:
import axios from "axios";
// Basic axios configuration
app.configure(rest("https://api.example.com").axios(axios));
// With custom axios instance
const axiosInstance = axios.create({
timeout: 5000,
headers: {
"Content-Type": "application/json"
}
});
app.configure(rest("https://api.example.com").axios(axiosInstance));
// With additional options
app.configure(rest("https://api.example.com").axios(axios, {
responseType: "json"
}));Configure REST transport using Superagent HTTP client library.
/**
* Configure Superagent transport
* @param connection - Superagent function
* @param options - Optional superagent configuration
* @returns Transport connection function
*/
superagent(connection: any, options?: any): TransportConnection;Usage Examples:
import superagent from "superagent";
// Basic superagent configuration
app.configure(rest("https://api.example.com").superagent(superagent));
// With custom options
app.configure(rest("https://api.example.com").superagent(superagent, {
timeout: 8000,
retry: 2
}));REST services automatically handle HTTP method mapping and URL generation.
/**
* REST service base class (internal implementation)
* Automatically maps service methods to HTTP requests
*/
abstract class Base<T = any, D = Partial<T>, P extends Params = Params> {
/** HTTP GET for find operation */
find(params?: RestClientParams<P>): Promise<Paginated<T> | T[]>;
/** HTTP GET for single resource */
get(id: Id, params?: RestClientParams<P>): Promise<T>;
/** HTTP POST for create operation */
create(data: D, params?: RestClientParams<P>): Promise<T>;
create(data: D[], params?: RestClientParams<P>): Promise<T[]>;
/** HTTP PUT for complete replacement */
update(id: NullableId, data: D, params?: RestClientParams<P>): Promise<T | T[]>;
/** HTTP PATCH for partial update */
patch(id: NullableId, data: Partial<D>, params?: RestClientParams<P>): Promise<T | T[]>;
/** HTTP DELETE for removal */
remove(id: NullableId, params?: RestClientParams<P>): Promise<T | T[]>;
/** Register custom HTTP methods */
methods(...names: string[]): this;
}
interface RestClientParams<P extends Params = Params> extends P {
/** HTTP client connection options */
connection?: any;
}HTTP Method Mapping:
| Service Method | HTTP Method | URL Pattern |
|---|---|---|
find() | GET | /service |
get(id) | GET | /service/:id |
create(data) | POST | /service |
update(id, data) | PUT | /service/:id |
patch(id, data) | PATCH | /service/:id |
remove(id) | DELETE | /service/:id |
Usage Examples:
// All service operations map to HTTP requests automatically
const userService = app.service("users");
// GET /users
const users = await userService.find();
// GET /users/123
const user = await userService.get(123);
// POST /users
const newUser = await userService.create({
name: "John Doe",
email: "john@example.com"
});
// PUT /users/123
const updatedUser = await userService.update(123, {
name: "John Smith",
email: "johnsmith@example.com"
});
// PATCH /users/123
const patchedUser = await userService.patch(123, {
name: "John Updated"
});
// DELETE /users/123
const removedUser = await userService.remove(123);REST transport automatically converts service params to URL query parameters.
Usage Examples:
// Query parameters are automatically converted to URL query string
const users = await userService.find({
query: {
active: true,
$limit: 10,
$skip: 20,
$sort: { name: 1 }
}
});
// Becomes: GET /users?active=true&$limit=10&$skip=20&$sort[name]=1
// Complex queries
const filteredUsers = await userService.find({
query: {
age: { $gte: 18, $lt: 65 },
$or: [
{ role: "admin" },
{ role: "moderator" }
]
}
});
// Becomes: GET /users?age[$gte]=18&age[$lt]=65&$or[0][role]=admin&$or[1][role]=moderatorREST services support custom methods beyond standard CRUD operations.
/**
* Register custom HTTP methods on the service
* @param names - Array of method names to register
* @returns Service instance for chaining
*/
methods(...names: string[]): this;Usage Examples:
// Register custom methods
const userService = app.service("users");
userService.methods("resetPassword", "sendWelcomeEmail");
// Custom methods become available (implementation depends on server)
// These would map to custom HTTP endpoints
await userService.resetPassword({ userId: 123, token: "reset-token" });
await userService.sendWelcomeEmail({ userId: 123, template: "welcome" });Pass custom headers and connection options with REST requests.
Usage Examples:
// Custom headers and connection options
const result = await userService.find({
query: { active: true },
headers: {
"X-Custom-Header": "value",
"Authorization": "Bearer token"
},
connection: {
// HTTP client specific options
timeout: 10000,
retry: 3
}
});
// Connection-specific options (varies by HTTP client)
const axiosResult = await userService.create(userData, {
connection: {
timeout: 5000,
responseType: "json",
validateStatus: (status) => status < 500
}
});REST transport automatically converts HTTP errors to FeathersJS error types.
Usage Examples:
import { errors } from "@feathersjs/client";
try {
const user = await userService.get(999);
} catch (error) {
if (error instanceof errors.NotFound) {
console.log("User not found");
} else if (error instanceof errors.BadRequest) {
console.log("Invalid request:", error.message);
} else if (error instanceof errors.NotAuthenticated) {
console.log("Authentication required");
}
}
// HTTP status codes are mapped to FeathersJS errors:
// 400 -> BadRequest
// 401 -> NotAuthenticated
// 403 -> Forbidden
// 404 -> NotFound
// 500 -> GeneralError
// etc.interface RestClientParams<P extends Params = Params> extends P {
/** HTTP client connection options */
connection?: {
timeout?: number;
headers?: Record<string, string>;
[key: string]: any;
};
}