Skip to content

gaeemmanuel/fake-api

Repository files navigation

Fake-api

Fake rest API for helping developers having test APIs when writing frontend applications. This project was generated with Node JS version 14.17.4.

Development server

Run node index.js for a dev server, the root URL is http://localhost:3000/.
You must restart the app every time you change any of the source files, unless you want to enable live-reload feature, in such a case, you should run npm run dev.

API documentation

Authentication

All GET requests are publicly accessible. However, when creating, updating or removing data, an JWT Bearer token will be required.

In order to obtain one, this API also provide endpoints for dealing with authentication:

  • /auth/login: Create new tokens for user (access token has a 3 minutes lifespan).

    fetch('http://localhost:3000/auth/login', {
      method: 'POST',
      body: JSON.stringify({
        username: 'John',
        password: 'MyPassword',
      }),
      headers: {
        'Content-type': 'application/json; charset=UTF-8',
      },
    })
      .then((response) => response.json())
      .then((json) => console.log(json));

    Output

    {
      "accessToken": "<accessToken>", // This token expires in 3 minutes"
      "refreshToken": "<refreshToken>" // This token only expires on logout or restart"
    }
  • /auth/token: Generate new access token from refresh token.

    fetch('http://localhost:3000/auth/token', {
      method: 'POST',
      body: JSON.stringify({
        token: '<refreshToken>',
      }),
      headers: {
        'Content-type': 'application/json; charset=UTF-8',
      },
    })
      .then((response) => response.json())
      .then((json) => console.log(json));

    Output

    {
      "accessToken": "<accessToken>", //A new access token which expires in 3 minutes"
      "refreshToken": null
    }
  • /auth/logout: Remove refresh token from memory (make it unusable for generating new access tokens).

    fetch('http://localhost:3000/auth/logout', {
      method: 'POST',
      body: JSON.stringify({
        token: '<refreshToken>',
      }),
      headers: {
        'Content-type': 'application/json; charset=UTF-8',
      },
    })
      .then((response) => response.json())
      .then((json) => console.log(json));

    Output

    {
      "date": "2021-01-01T00:00:00.007Z",
      "loggedOut": true // False mean that the refresh token weren't found in memory.
    }
  • /auth/whoami: Getting current authenticated user.

    fetch('http://localhost:3000/auth/whoami', {
      method: 'GET',
      headers: {
        'Content-type': 'application/json; charset=UTF-8',
        Authorization: 'Bearer <accessToken>',
      },
    })
      .then((response) => response.json())
      .then((json) => console.log(json));

    Output

    {
      "id": 1,
      "name": "Leanne Graham",
      "role": "Standard",
      "title": "Geek",
      "username": "Bret",
      "password": "password123",
      "email": "Sincere@april.biz",
      "address": {...},
      "phone": "1-770-736-8031 x56442",
      "website": "hildegard.org",
      "company": {...}
    }

Endpoints

This API provide 6 different resources available at the following URLs:

Note: These data are copied from JsonPlaceHolder and saved in the data folder of this repository.

Routes

Note that all GET routes are publicly accessible (no authentication required) while POST/PUT/DELETE need an authorization header.

Each previously mentioned resource define the following operations:

  • GET: For fetching page of data (see pagination section).

    fetch('http://localhost:3000/posts')
      .then((response) => response.json())
      .then((json) => console.log(json));

    Output

    {
     "page": 1,
     "size": 10,
     "count": 10,
     "totalElements": 100,
     "totalPages": 10,
     "data": [
         {
             "userId": 1,
             "id": 1,
             "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
             "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
         },
         ...
     ]
    }
  • GET: For fetching a single record by its ID.

    fetch('http://localhost:3000/posts/1')
      .then((response) => response.json())
      .then((json) => console.log(json));

    Output

    {
      "userId": 1,
      "id": 1,
      "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
      "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
    }
  • POST: For creating new data (no data validation but authentication required).

    fetch('http://localhost:3000/posts', {
      method: 'POST',
      body: JSON.stringify({
        title: 'foo',
        body: 'bar',
        userId: 1,
      }),
      headers: {
        'Content-type': 'application/json; charset=UTF-8',
        Authorization: 'Bearer <accessToken>',
      },
    })
      .then((response) => response.json())
      .then((json) => console.log(json));

    Output

    {
      "id": 101,
      "title": "foo",
      "body": "bar",
      "userId": 1
    }
  • PUT: For updating the record with provided ID (no data validation but authentication required).

    fetch('http://localhost:3000/posts/1', {
      method: 'PUT',
      body: JSON.stringify({
        id: 1,
        title: 'foo',
        body: 'bar',
        userId: 1,
      }),
      headers: {
        'Content-type': 'application/json; charset=UTF-8',
        Authorization: 'Bearer <accessToken>',
      },
    })
      .then((response) => response.json())
      .then((json) => console.log(json));

    Output

    {
      "id": 101,
      "title": "foo",
      "body": "bar",
      "userId": 1
    }
  • DELETE: For removing the record with provided ID (authentication required).

    fetch('http://localhost:3000/posts/1', {
      method: 'DELETE',
      headers: {
        Authorization: 'Bearer <accessToken>',
      },
    });

    Output

    {
      "removed": 1
    }
  • DELETE: For removing all records (authentication required).

    fetch('http://localhost:3000/posts', {
      method: 'DELETE',
      headers: {
        Authorization: 'Bearer <accessToken>',
      },
    });

    Output

    {
      "removed": 100
    }

Note: These data are copied from JsonPlaceHolder and saved in the data folder of this repository.
Also keep in mind that the data will be restarted to default one every time you restart your Node JS application.

Pagination

This API provide a pagination feature with the following key words:

  • page: One-based index of the page to display (if none provided, the default value 1 will be used).

  • size: Number of records to display on each page (if none provided, the default value 10 will be used).

The following request will browse the third page, each page containing 15 records.

fetch('http://localhost:3000/posts?page=3&size=15')
  .then((response) => response.json())
  .then((json) => console.log(json));

Filtering

This API provide a filtering feature triggered by the keyword filters in URL query parameters.

Each filtering operation is a new query parameter filters added to the URL.

Operands in a single operation are delimited by a colon (",").

Final URL will be similar to http://hostname/modelname?filters=**field_1,operator_1,value_1**&filters=**field_2,operator_2,value_2**...

The API currently supports these operators:

  • equal: ==
  • not equal: !=
  • greater than: >
  • greater than or equal: >=
  • lesser than: <
  • lesser than or equal: <=
  • in: in
  • not in: notIn
  • like: like
  • not like: notLike

Here are some examples (note that the filters param values may need escaping depending on your system):

Please also note that you can do (basic) logical operations between one filter operations and the previously applied ones. By default, when multiple filtering operations are applied, the API will do an and-operation (condition_N && condition_N+1 &&...). You can alter this behavior by prefixing the field's name of the next operation with a pipe (|). (condition_N || condition_N+1 || ...). All operations are applied in FIFO, without any relation of priority between them: condition_N || condition_N+1 && condition_N+2 will apply the mathematical operation (condition_N || condition_N+1) && condition_N+2.

Sorting

This API provide a sorting feature triggered by the keyword sortBy in URL query parameters.

Each sorting operation is a new query parameter sortBy added to the URL.

For a single sorting operation, we must retrieve the field of the record to base the sorting on, and also the direction of this sorting, separated from field's name by a colon (",").

Final URL will be similar to http://localhost:3000/posts?**sortBy=field_1,direction_1**&**sortBy=field_2,direction_2**...

The API currently supports these two directions:

  • asc: Sorting in an ascending order based on field's value.
  • desc: Sorting in a descending order based on field's value.

Please note that if you omit the direction in the sortBy parameter's value, it will be considered as an ascending sorting direction. Also note that when no sorting instructions is provided in URL, the API will return the results by sorting them on their ID.

Here are some examples:

Swagger

This API also exposes its documentation by using Swagger features. This documentation is available under the endpoint: http://localhost:3000/api-docs.

The Swagger definition can also imported in other tools like Postman; to do so, just provide Postman with the JSON documentation available at http://localhost:3000/swagger.json.

TODO

These features will eventually be implemented later:

  • nested lookup (applying filtering on nested models)
  • nested sorting (applying sorting on nested models)

About

Fake rest API for helping developpers having test APIs when writing frontend applications.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors