DEV Community

Cover image for Building a Dynamic Profile Endpoint — GET /me (Node.js/Express + Cat Facts)
Yahaiii
Yahaiii

Posted on

Building a Dynamic Profile Endpoint — GET /me (Node.js/Express + Cat Facts)

I built a small Node.js/Express API with GET /me that returns a JSON profile object plus a live cat fact. The endpoint always returns a consistent schema, a UTC ISO-8601 timestamp, and fetches a new cat fact per request (2s timeout, graceful fallback).

Repository:

https://github.com/yahaiii/hng13-stage0-profile-endpoint

Tech stack

  • Node.js + Express
  • axios (external API fetch)
  • express-rate-limit + morgan (rate limiting + logging)
  • dotenv (env vars)
  • Jest + Supertest (tests)

Goals

The /me endpoint must:

  • Respond to GET /me with HTTP 200
  • Content-Type: application/json
  • Return JSON exactly in this shape:
{
  "status": "success",
  "user": {
    "email": "<your email>",
    "name": "<your full name>",
    "stack": "<your backend stack>"
  },
  "timestamp": "<current UTC time in ISO 8601 format>",
  "fact": "<random cat fact from Cat Facts API>"
}
Enter fullscreen mode Exit fullscreen mode
  • timestamp is the current UTC time in ISO 8601 and updates each request
  • fact is fetched from https://catfact.ninja/fact on every request (no caching)
  • Graceful fallback when external API is down

Implementation (high level)

  • Express app is exported from index.js. server.js starts the listener — this makes tests import the app directly for CI-friendly tests.
  • The /me route:
    • Reads EMAIL, FULL_NAME, STACK from .env
    • Timestamp: new Date().toISOString()
    • Calls https://catfact.ninja/fact with axios and a 2000ms timeout
    • On success: use response.data.fact
    • On error/timeout: fallback string "Cat fact unavailable at the moment."
    • Returns JSON with status: "success", user, timestamp, and fact
  • Basic rate limiting and request logging applied for public deployments

Example handler (illustrative):

// example snippet
const axios = require('axios');

async function getMe(req, res) {
  const user = {
    email: process.env.EMAIL || 'your-email@example.com',
    name: process.env.FULL_NAME || 'Your Full Name',
    stack: process.env.STACK || 'Node.js/Express'
  };

  const timestamp = new Date().toISOString();

  let fact = 'Cat fact unavailable at the moment.';
  try {
    const r = await axios.get('https://catfact.ninja/fact', { timeout: 2000 });
    if (r?.data?.fact) fact = r.data.fact;
  } catch (err) {
    console.error('Cat fact fetch failed:', err.message);
  }

  return res.json({ status: 'success', user, timestamp, fact });
}
Enter fullscreen mode Exit fullscreen mode

How I tested locally (PowerShell)

cd 'c:\path\to\the\project\'
npm install
copy .env.example .env
# edit .env -> set EMAIL and FULL_NAME (and STACK if desired)
npm start
# verify
curl http://localhost:3000/me
# run tests (no server start required; tests import the app)
npm test
Enter fullscreen mode Exit fullscreen mode

Challenges & tradeoffs

  • Returned HTTP 200 with a fallback fact when the external API fails. This keeps the consumer schema stable; alternative is a 502 when downstream fails.
  • Short 2s timeout avoids hanging requests; production may need retry/backoff or circuit breaker.
  • Integration tests call the real external API; for deterministic CI, mock axios responses.

What I learned

  • Exporting the app for tests simplifies CI and avoids starting/stopping servers.
  • Keep API response schemas stable for client reliability.
  • Simple defensive code (timeouts, fallbacks) improves resilience.

Next steps

  • Add axios mocks for deterministic unit tests
  • Improve observability (structured logs, tracing)
  • Add a short TTL cache if external API rate is a concern
  • Add GitHub Actions to run tests on push

Top comments (2)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.