This documentation is for Version
1.x
please check the main branch for latest version documentation.
An Axios Based Package and Promise based HTTP client for the browser and node.js.
Axios is an awesome library, and provides you with great features, however, there are some missing features that is needed in most of our real world projects:
For demonstration purpose only, we may use React syntax for illustration when dealing with forms.
yarn add @mongez/http
Or
npm i @mongez/http
Let's start with our first step, defining http configuration.
import { setHttpConfigurations } from '@mongez/http';
setHttpConfigurations({
baseUrl: 'https://sitename.com/api',
});
From this step we can now use our relative paths to our base url we set in our configurations.
We'll go later with the rest of our configurations, now let's start using it.
// src/services/auth.ts
import endpoint from '@mongez/http';
export function login(data: object) {
return endpoint.post('/login', data);
}
// in some component base file
// some-component.ts
const onSubmit = e => {
const data = {
email: 'hassanzohdy@gmail.com',
password: '123456789',
};
login(data).then(response => {
// response is done
}).catch(error => {
// some error in the response
});
};
In some situations, such as Admin Dashboard, there would be pages that implements CRUD Operations, thankfully, this can be done easily with RestfulEndpoint
class, which you provide the route of the CRUD requests, and it handles all Restful API.
// src/services/users-service.ts
import { RestfulEndpoint } from '@mongez/http';
class UsersService extends RestfulEndpoint {
/**
* {@inheritDoc}
*/
public route: string = '/users';
}
const usersService: UsersService = new UsersService();
export default usersService;
From this point we can now use our usersService
object to list
get
create
update
delete
patch
or publish
To get a list of records, we can use list
method which is defined by default in RestfulEndpoint
class.
// src/index.ts
import usersService from './services/users-service';
// list users without any params sent
// request: GET /users
usersService.list().then(response => {
//
});
We may also send params as a query string to the request as well
// src/index.ts
import usersService from './services/users-service';
// request: GET /users?paginate=true&itemsPerPage=15
const params: object = {
paginate: true,
itemsPerPage: 15,
};
usersService.list(paramsList).then(response => {
//
});
To get a single record, use get
method.
// src/index.ts
import usersService from './services/users-service';
// get user information
const userId: number = 1;
// request: GET /users/1
usersService.get(userId).then(response => {
//
});
// get user with additional params sent with the request
// request: GET /users/1?active=true
usersService.get(userId, {
active: true
}).then(response => {
//
});
We may also send additional params with the single record as a query string.
// src/index.ts
import usersService from './services/users-service';
// get user information
const userId: number = 1;
const params: object = {
active: true
};
// get user with additional params sent with the request
// request: GET /users/1?active=true
usersService.get(userId, params).then(response => {
//
});
Creating a new record can be done from the endpoint service using create
method.
Check acceptable types of data at Acceptable Http Data Section.
// src/index.ts
import usersService from './services/users-service';
const data: object = {
email: 'hassanzohdy@gmail.com',
password: '123456789',
confirmPassword: '123456789',
};
// POST /users
usersService.create(data).then(response => {
// user request is created successfully.
});
Updating an existing record is also can be done using update
method.
Check acceptable types of data at Acceptable Http Data Section.
// src/index.ts
import usersService from './services/users-service';
const data: object = {
email: 'hassanzohdy@gmail.com',
password: '123456789',
confirmPassword: '123456789',
};
const id: number = 1;
// PUT /users/1
usersService.update(id, data).then(response => {
// user resource is updated successfully.
});
Creating a small updates on records can be done use patch
method.
// src/index.ts
import usersService from './services/users-service';
const data: object = {
published: true
};
const id: number = 1;
// PATCH /users/1
usersService.patch(id, data).then(response => {
// user resource is patched successfully.
});
A smaller method that allow you to publish/un-publish records using publish
method.
// src/index.ts
import usersService from './services/users-service';
const isPublished: boolean = true;
const id: number = 1;
// PATCH /users/1
// request payload: { published: true }
usersService.publish(id, isPublished).then(response => {
// user resource is patched successfully.
});
You may change the published
key to another key by passing your desired key in the third argument.
// src/index.ts
import usersService from './services/users-service';
const isActivated: boolean = true;
const id: number = 1;
// PATCH /users/1
// request payload: { activated: true }
usersService.publish(id, isActivated, 'activated').then(response => {
// user resource is patched successfully.
});
Our final method in the Restful API concept is to delete a resource/record.
// src/index.ts
import usersService from './services/users-service';
const id: number = 1;
// DELETE /users/1
usersService.delete(id).then(response => {
// user resource is patched successfully.
});
In some cases we may need to create custom methods that can be used later in our project.
// src/services/users-service.ts
import { RestfulEndpoint } from '@mongez/http';
class UsersService extends RestfulEndpoint {
/**
* {@inheritDoc}
*/
public route: string = '/users';
/**
* Get active members only
*/
public listActive() {
return this.endpoint.get(this.path('/active'));
}
}
const usersService: UsersService = new UsersService();
export default usersService;
In the previous example, we created a new method listActive
which calls endpoint instance this.endpoint
and pass to it a path
method, this method concatenate the given argument with the basic route to generate another route, in the previous example the final route will be /users/active
.
All of the previous methods list
get
create
update
delete
patch
or publish
their last argument accepts Axios Configurations that can be Request Config.
Another good feature of @mongez/http
is that you can cancel or abort your last request easily using lastRequest
function.
import endpoint, { lastRequest } from '@mongez/http';
endpoint.get('/user').then(response => {
// it nevers go here
});
// from some other point
lastRequest().abort();
If you're making multiple requests, cache the last request function in a variable as calling it always returns last fired request.
import endpoint, { lastRequest } from '@mongez/http';
endpoint.get('/user').then(response => {
// it nevers go here
});
const usersRequest = lastRequest();
endpoint.get('/posts').then(response => {
// it nevers go here
});
usersRequest.abort();
const postsRequest = lastRequest();
postsRequest.abort();
For POST
PUT
requests, there are four acceptable formats of data:
object
: which will send the request as json.HTMLFormElement
which accepts an instance of HTMLFormElement and request data will be sent as form data.FormData
which accepts an instance of FormData and request data will be sent as form data.string
which will be sent as a string.
Let's see an example for each format.
In the next example, we'll see how to use an example of sending post request using plain object.
If data is sent as plain object, then a request header
"Content-Type": "Application/json"
will be added to headers by default.
import endpoint from '@mongez/http';
const data: object = {
email: 'hassanzohdy@gmail.com',
password: '123456789',
}
endpoint.post('/login', data).then(response => {
//
});
In the next example, we'll see how to use an example of sending post request using form element.
// Form.tsx
import React from 'react';
import endpoint from '@mongez/http';
export default function MyForm() {
const submitForm = e => {
e.preventDefault();
const formElement: HTMLFormElement = e.target;
endpoint.post('/login', formElement).then(response => {
//
});
}
return (
<form onSubmit={submitForm}>
<input name="email" type="email" />
<input name="password" type="password" />
</form>
)
}
In the next example, we'll see how to use an example of sending post request using form data.
// Form.tsx
import React from 'react';
import endpoint from '@mongez/http';
export default function MyForm() {
const submitForm = e => {
e.preventDefault();
const formElement: HTMLFormElement = e.target;
const formData = new FormData(formElement);
endpoint.post('/login', formData).then(response => {
//
});
}
return (
<form onSubmit={submitForm}>
<input name="email" type="email" />
<input name="password" type="password" />
</form>
)
}
Sometimes your api accepts only json data, but you may work with form elements or form data as well for storing form information, you may set an option to auto convert any form element or form data to json automatically in every request, just set formDataToJSON
option to true in http configurations list.
import { setHttpConfigurations } from '@mongez/http';
setHttpConfigurations({
baseUrl: 'https://sitename.com/api',
formDataToJSON: true,
});
You may also set your serializer method to convert the form data elements to objects.
import { setHttpConfigurations } from '@mongez/http';
setHttpConfigurations({
baseUrl: 'https://sitename.com/api',
formDataToJSON: true,
formDataToJSONSerializer: (formData: FormData): object => {
// convert it into an object
return {};
},
});
If your backend api requires Authorization
header in every request, You may set Authorization header from configurations either as a string or as a callback,
import { setHttpConfigurations } from '@mongez/http';
setHttpConfigurations({
baseUrl: 'https://sitename.com/api',
setAuthorizationHeader: 'key some-api-key'
});
You can set it as a callback so it gets a bearer token for example
import user from './src/some-user';
import { setHttpConfigurations } from '@mongez/http';
setHttpConfigurations({
baseUrl: 'https://sitename.com/api',
setAuthorizationHeader: () => {
if (user.isLoggedIn()) {
return `Bearer ${user.accessToken()}`;
}
return `key some-api-key`;
}
});
Why? because PUT requests won't allow sending files whereas post requests do it, so in some backend frameworks like Laravel has a nice workaround that allows you to send a post request and it handles it as put request.
If your backend allows something like this, you may wish to set putToPost
option to true.
import { setHttpConfigurations } from '@mongez/http';
setHttpConfigurations({
baseUrl: 'https://sitename.com/api',
putToPost: true,
});
This will convert any put request to post request with _method
key added to the request payload with value PUT
.
import endpoint, { setHttpConfigurations } from '@mongez/http';
setHttpConfigurations({
baseUrl: 'https://sitename.com/api',
putToPost: true,
});
// The request will be:
// POST /users/1
// Request Payload: {email: some-email@gmail.com, _method: PUT}
endpoint.put('/users/1', {
email: 'some-email@gmail.com',
});
You may also override the _method
key to other key if you would like in your http configurations.
import { setHttpConfigurations } from '@mongez/http';
setHttpConfigurations({
baseUrl: 'https://sitename.com/api',
putToPost: true,
putMethodKey: '_other_put_key'
});
// The request will be:
// POST /users/1
// Request Payload: {email: some-email@gmail.com, _other_put_key: PUT}
endpoint.put('/users/1', {
email: 'some-email@gmail.com',
});
The following snippet defines all available configurations to the package.
type HttpConfigurations = {
/**
* Base Url Request
*/
baseUrl?: string;
/**
* If set to true, all PUT requests will be transformed to POST requests with _method = PUT value will be appended.
*
* @default false
*/
putToPost?: boolean;
/**
* Defines the put key that will be added to post requests.
* Works only if `putToPost` is set to true and you send a `put` request
* The send value is `PUT`
*
* @default _method
*/
putMethodKey?: string;
/**
* Set other axios setup configurations
*/
axiosConfig?: AxiosRequestConfig;
/**
* If set to true, any data that is sent as HTMLFormElement or FormData will be converted into object json format.
*
* @default false
*/
formDataToJSON?: boolean;
/**
* A serializer function that accepts FormData element
* and returns an object to be transformed into JSON
*/
formDataToJSONSerializer?: (formData: FormData) => object;
/**
* Set authorization header
*
* Useful when using Key and Bearer Tokens
*/
setAuthorizationHeader?: string | (() => string);
};
Mongez Http
is shipped with event driven approach so you may manipulate requests before sending it or after response is sent either on success, fail or on both.
Before sending any request:
import { AxiosRequestConfig } from "axios";
import { endpointEvents } from '@mongez/http';
import { EventSubscription } from "@mongez/events";
// This is triggered before sending any request
endpointEvents.beforeSending((requestConfig:AxiosRequestConfig): EventSubscription => {
// do something
});
On success request:
import { AxiosResponse } from "axios";
import { endpointEvents } from '@mongez/http';
import { EventSubscription } from "@mongez/events";
// This is triggered on success request
endpointEvents.onSuccess((response: AxiosResponse): EventSubscription => {
// do something
});
On Failure request:
import { AxiosResponse } from "axios";
import { endpointEvents } from '@mongez/http';
import { EventSubscription } from "@mongez/events";
// This is triggered on failure request
endpointEvents.onError((response: AxiosResponse): EventSubscription => {
// do something
});
On request response either success or failure:
import { AxiosResponse } from "axios";
import { endpointEvents } from '@mongez/http';
import { EventSubscription } from "@mongez/events";
// This is triggered on response return either on success or on failure
endpointEvents.onResponse((response: AxiosResponse): EventSubscription => {
// do something
});
- 1.0.22 (1 Feb 2022)
- Fixed Incorrect base url concatenation with request config url.
- 1.0.21 (31 Jan 2022)
- Fixed lastRequest incorrect Cancel Token Clone.
- Added
LastRequest
as return type tolastRequest()
function.
- Add Unit Tests
- Handle Nodejs Http Requests.
- Adding events on
RestfulEndpoint
i.eonListing
onCreating
and so on.