
Modern applications communicate with other servers to accomplish tasks like sending emails, upload/download images, and embedding live Twitter feed. That is when we need HTTP requests. There are multiple ways to make HTTP requests in Node.js. In this article, I am going to introduce the Axios library.
Axios is a JavaScript library that works in both Browser and Node.js platforms. Axios is promise-based, and this lets us perform requests asynchronously.
Implementation
Let's implement a feature in the Node.js-React application I created in the last article that accepts a URL as an input from a user, load the content of the URL, and counts the number of word occurrence in its DOM. I am going to use a URL of a large .txt document of The Mysterious Affair at Styles by my favorite mystery writer, Agatha.
Before we move on, let's create api/app.js and edit api/server.js to separate responsibilities:
// api/app.js
const express = require("express")
const app = express()
const cors = require("cors")
app.use(cors())
app.post("/", function (req, res) {
 // fetch the content from the URL
 // clean the content
 // count the word occurrence and send it back
})
module.exports = app
// api/server.js
const app = require("./app")
app.listen(3000, () => {
  console.log("app listening on port 3000")
})
Now, let's create a module for each task:
- Fetch the content from the URL
 - Clean the content
 - Count the word occurrence ***
 
Fetch the content from the URL
First, we need to install axios. Run:
$ cd api
$ npm install axios
Create api/fetch-url-content.js and write:
// api/fetch-url-content
const axios = require('axios')
exports.fetchUrlContent = url => {
  return axios.get(url)
    .then(response => {
      return response.data
    })
    .catch(error => {
      console.log(error)
    })
}
response.data is the response that was provided by the server. Let's use catch for error handling.
Clean the content
To count the occurrence properly, we should:
- Remove numbers
 - Remove special characters except for apostrophes that are part of the words
 - Replace 2 or more spaces to 1
 - Remove whitespace from both ends of a string
 - Convert strings to lowercase
 
To do this, we need Regular Expression. Create api/clean.js and write:
// api/clean.js
exports.clean = string => {
  const alphabet = string.replace(/[^A-Za-z']+/g, " ").trim()
  const lowerCase = alphabet.toLowerCase()
  return lowerCase
}
As the replace() method searches a string for a specified value and returns a new string where the specified values are replaced, .replace(/[^A-Za-z']+/g, " ") replaces everything besides alphabets, and apostrophes that are neither ends of a string with one space.
The trim() method removes whitespace from both ends of a string.
The toLowerCase() method returns the calling string value converted to lower case.
Count the word occurrence
Let's create api/count.js and implement a function to count the word occurrence of cleaned string:
// api/count.js
exports.count = string => {
  let map = {}
  const words = string.split(" ").filter(word => word !== "")
  for (let i = 0; i < words.length; i++) {
    const item = words[i]
    map[item] = (map[item] + 1) || 1
  }
  return map
}
Call the functions asyncronously
Now in api/app.js, we can call functions provided by each module:
// api/app.js
app.post("/", async function (req, res) {
  const url = req.body.url
  const content = await fetchUrlContent(url)
  const cleanedContent = clean(content)
  const result = count(cleanedContent)
  res.send(result)
})
We need async and await to wait for the fetchUrlContent function to finish executing and then run the rest of the POST method.
  
  
  Use body-parser to simplify the POST request
Also, it is better to use the body-parser Express middleware to read the body of incoming request data, and simplify it. This time we use express.json() and express.urlencoded.
Now, api/app.js should look like this:
// api/app.js
const express = require("express")
const app = express()
const cors = require("cors")
const { fetchUrlContent } = require("./fetch-url-content")
const { clean } = require("./clean")
const { count } = require("./count")
app.use(cors())
app.use(express.urlencoded(({ extended: true })))
app.post("/", async function (req, res) {
  const url = req.body.url
  const content = await fetchUrlContent(url)
  const cleanedContent = clean(content)
  const result = count(cleanedContent)
  res.send(result)
})
module.exports = app
Build the client
Lastly, let's build a form and a table in client/App.js for UI:
// client/App.js
import React from "react"
import "./App.css" // Added some styling
class App extends React.Component {
  state = {
    url: "",
    result: {}
  }
  genRows = obj => {
    return Object.keys(obj).map(key => {
      return (
        <tr key={key}>
          <td>{key}</td>
          <td>{obj[key]}</td>
        </tr>
      )
    })
  }
  submitHandler = e => {
    e.preventDefault()
    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Accepts: "application/json",
      },
      body: JSON.stringify({
        url: this.state.url,
      }),
    }
    fetch("http://localhost:3000/", options)
      .then(res => res.json())
      .then(data => {
        this.setState({ result: data, url: "" })
      })
  }
  render() {
    return (
      <>
        <h1>Word Counter</h1>
        <form onSubmit={e => this.submitHandler(e)}>
          <label>
            URL:
          <input
              type="url"
              name="url"
              onChange={e => this.setState({ url: e.target.value })}
              value={this.state.url} />
          </label>
          <input type="submit" value="Submit" />
        </form>
        <table>
          <thead>
            <tr>
              <th>Word</th>
              <th>Count</th>
            </tr>
          </thead>
          <tbody>
              {this.genRows(this.state.result)}
          </tbody>
        </table>
      </>
    )
  }
}
export default App
This is it! Let's see what we get from The Mysterious Affair at Styles:

    
Top comments (2)
Hey did u get this output from backend
{"object": 1,
"promise": 1
}
when i tried to pass the url from the frontend and i for an error from the backend that is,
TypeError [ERR_INVALID_URL]: Invalid URL
but i directly pass the url from backend , i got the above object as output
This is the frontend code
could u please check
`import './App.css';
import { useState } from 'react';
function App() {
const [url, setUrl] = useState("");
const [result, setResult] = useState({});
const genRows=obj=>{
return Object.keys(obj).map(key=>{
return(
)
})
}
const submitHandler=e=>{
e.preventDefault()
const options={
method:'POST',
headers:{
"content-type":"application/json",
Accepts:"application/json",
},
body:JSON.stringify({url:url}),
}
fetch('localhost:5000/',options)
.then(res=>res.json()).then(data=>{
setResult({result:data})
// setUrl('')
})
}
return (
WORD COUNTER
submitHandler(e)}>
type="url"
name="url"
placeholder='Enter The URL'
onChange={e=>setUrl(e.target.value)}
value={url}
/>
{genRows(result)}
);
}
export default App;
`
Thanks for the tutorial!
Quick note - I had to add the following line in server.js to make it work:
app.use(express.json())