February 10: Pagination in a json-server API with the link header

Background: What’s pagination?

Uh, okay… so?

Starting up json-server

\{^_^}/ hi!Loading db.json
Done
Resources
http://localhost:3000/us-counties
Home
http://localhost:3000
Type s + enter at any time to create a snapshot of the database
{
"us-counties": [
{
"population": 55200,
"state": "Alabama",
"name": "Autauga",
"type": "County"
},
{
"population": 208107,
"state": "Alabama",
"name": "Baldwin",
"type": "County"
},
...

Exploring the link header

<http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=1>; rel="first", <http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=2>; rel="prev", <http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=4>; rel="next", <http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=7>; rel="last"
fetch( currentUrl ).then( response => response.headers.get( "Link" ) ).then(...);

Parsing the link header

function parseLinkHeader( linkHeader ) {
return Object.fromEntries( linkHeader.split( ", " ).map( header => header.split( "; " ) ).map( header => [ header[1].replace( /"/g, "" ).replace( "rel=", "" ), header[0].slice( 1, -1 ) ] ) );
}
function parseLinkHeader( linkHeader ) {
const linkHeadersArray = linkHeader.split( ", " ).map( header => header.split( "; " ) );
const linkHeadersMap = linkHeadersArray.map( header => {
const thisHeaderRel = header[1].replace( /"/g, "" ).replace( "rel=", "" );
const thisHeaderUrl = header[0].slice( 1, -1 );
return [ thisHeaderRel, thisHeaderUrl ]
} );
return Object.fromEntries( linkHeadersMap );
}
[
[ '<http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=1>', 'rel="first"' ],
[ '<http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=2>', 'rel="prev"' ],
[ '<http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=4>', 'rel="next"' ],
[ '<http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=7>', 'rel="last"' ]
]
{
first: 'http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=1',
prev: 'http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=2',
next: 'http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=4',
last: 'http://localhost:3000/us-counties?state=New%20York&_limit=10&_page=7'
}

Putting the link header to use

let currentUrl = "http://localhost:3000/us-counties?_limit=20&_page=1"function paginate( direction ) {
fetch( currentUrl ).then( response => {
let linkHeaders = parseLinkHeader( response.headers.get( "Link" ) );
if ( !!linkHeaders[ direction ] ) {
currentUrl = linkHeaders[ direction ];
fetchCounties( linkHeaders[ direction ] );
}
} );
}

Conclusion: Here I go, playin’ the star again — there I go, turn the page…

--

--

--

Oh geez, Josh Frank decided to go to Flatiron? He must be insane…

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

How To Pass the Microsoft Azure Fundamentals Exam

Open API, an unmixed blessing for agile downstream dynamics or a quicksand ?

Rich Push Notification with Firebase Cloud Messaging (FCM) and Pusher in iOS platform

Azure functions with Docker. How does this work?

How product usage tracking can violate privacy

Lawyers in Utah

lawyers in utah

Tips to Create HTML Email That Works with All Email Clients (Part 1)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Josh Frank

Josh Frank

Oh geez, Josh Frank decided to go to Flatiron? He must be insane…

More from Medium

Customising JSON Forms

Atomic Design System in Frontend

1. Todo Web App with react hooks: Add Task

Best Practices for Cookie Notifications