Skip to content

Latest commit

 

History

History
432 lines (345 loc) · 11 KB

File metadata and controls

432 lines (345 loc) · 11 KB

Job Listings API

A secure, efficient, and well-documented RESTful API for managing job listings. Built with Node.js, Express, and MongoDB, following industry best practices for security, performance, and code quality.

📋 Table of Contents

✨ Features

  • Full CRUD Operations - Create, Read, Update, and Delete job listings
  • Pagination - Efficient data retrieval with customizable page sizes
  • Search & Filtering - Search jobs by title, description, company, location, and salary range
  • Input Validation - Comprehensive request validation using express-validator
  • Security Hardened - Helmet.js, CORS, rate limiting, and input sanitization
  • Error Handling - Consistent error responses with proper HTTP status codes
  • Request Logging - Morgan-based request logging for monitoring
  • Health Check Endpoint - Monitor API availability
  • Graceful Shutdown - Proper cleanup on server termination

🛠 Tech Stack

Technology Purpose
Node.js Runtime environment
Express.js Web framework
MongoDB Database
Mongoose MongoDB ODM
Helmet Security headers
CORS Cross-Origin Resource Sharing
express-rate-limit Rate limiting
express-validator Input validation
Morgan HTTP request logging
dotenv Environment configuration

📦 Prerequisites

Before running this application, ensure you have the following installed:

  • Node.js (v18.0.0 or higher) - Download
  • MongoDB - Choose ONE of the following options:
    • Option A: MongoDB Atlas (Recommended - Free Cloud) - Sign up free
    • Option B: Local MongoDB (v6.0 or higher) - Download
    • Option C: Docker - docker run -d -p 27017:27017 --name mongodb mongo:latest
  • npm (comes with Node.js) or yarn

MongoDB Atlas Setup (Free Cloud Database)

If you don't want to install MongoDB locally, follow these steps:

  1. Go to MongoDB Atlas and create a free account
  2. Create a new FREE shared cluster (M0 tier)
  3. In Database Access, create a database user with password
  4. In Network Access, add your IP address (or 0.0.0.0/0 for development)
  5. Click ConnectConnect your application → Copy the connection string
  6. Replace <password> with your database user's password
  7. Update your .env file:
    MONGODB_URI=mongodb+srv://username:password@cluster0.xxxxx.mongodb.net/jobListings?retryWrites=true&w=majority

🚀 Installation

  1. Clone the repository

    git clone <repository-url>
    cd job-listings-api
  2. Install dependencies

    npm install
  3. Set up environment variables

    # Copy the example environment file
    cp .env.example .env
    
    # Edit .env with your configuration

⚙️ Configuration

Create a .env file in the root directory with the following variables:

Variable Description Default
PORT Server port number 3000
NODE_ENV Environment mode (development or production) development
MONGODB_URI MongoDB connection string mongodb://localhost:27017/jobListings
RATE_LIMIT_WINDOW_MS Rate limit time window in milliseconds 900000 (15 min)
RATE_LIMIT_MAX_REQUESTS Maximum requests per window 100

Example .env file:

PORT=3000
NODE_ENV=development
MONGODB_URI=mongodb://localhost:27017/jobListings
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100

▶️ Running the Application

Development Mode (with auto-reload)

npm run dev

Production Mode

npm start

The server will start on http://localhost:3000 (or your configured PORT).

📖 API Documentation

Base URL

http://localhost:3000/api

Endpoints Overview

Method Endpoint Description
GET /health Health check
GET /api/jobs Get all jobs (paginated)
GET /api/jobs/:id Get a specific job
POST /api/jobs Create a new job
PUT /api/jobs/:id Update a job
DELETE /api/jobs/:id Delete a job

Health Check

Check if the API is running.

Request:

GET /health

Response:

{
  "status": "OK",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "uptime": 3600.5
}

Get All Jobs

Retrieve a paginated list of jobs with optional filtering.

Request:

GET /api/jobs?page=1&limit=10&search=developer&company=Tech&location=Remote&minSalary=50000&maxSalary=150000

Query Parameters:

Parameter Type Description Default
page integer Page number (min: 1) 1
limit integer Items per page (1-100) 10
search string Search in title and description -
company string Filter by company name -
location string Filter by location -
minSalary number Minimum salary filter -
maxSalary number Maximum salary filter -

Response:

{
  "data": [
    {
      "id": "507f1f77bcf86cd799439011",
      "title": "Senior Software Developer",
      "description": "We are looking for an experienced developer...",
      "company": "Tech Corp",
      "location": "Remote",
      "salary": 120000,
      "datePosted": "2024-01-15T10:30:00.000Z",
      "createdAt": "2024-01-15T10:30:00.000Z",
      "updatedAt": "2024-01-15T10:30:00.000Z"
    }
  ],
  "pagination": {
    "currentPage": 1,
    "totalPages": 5,
    "totalItems": 48,
    "itemsPerPage": 10,
    "hasNextPage": true,
    "hasPrevPage": false
  }
}

Get Job by ID

Retrieve a specific job by its ID.

Request:

GET /api/jobs/507f1f77bcf86cd799439011

Response:

{
  "data": {
    "id": "507f1f77bcf86cd799439011",
    "title": "Senior Software Developer",
    "description": "We are looking for an experienced developer...",
    "company": "Tech Corp",
    "location": "Remote",
    "salary": 120000,
    "datePosted": "2024-01-15T10:30:00.000Z",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-15T10:30:00.000Z"
  }
}

Create a Job

Create a new job listing.

Request:

POST /api/jobs
Content-Type: application/json

{
  "title": "Senior Software Developer",
  "description": "We are looking for an experienced developer to join our team. Must have 5+ years of experience with Node.js and React.",
  "company": "Tech Corp",
  "location": "Remote",
  "salary": 120000
}

Request Body:

Field Type Required Constraints
title string Yes 3-100 characters
description string Yes 10-5000 characters
company string Yes 2-100 characters
location string Yes 2-100 characters
salary number Yes Positive number

Response (201 Created):

{
  "message": "Job created successfully",
  "data": {
    "id": "507f1f77bcf86cd799439011",
    "title": "Senior Software Developer",
    "description": "We are looking for an experienced developer...",
    "company": "Tech Corp",
    "location": "Remote",
    "salary": 120000,
    "datePosted": "2024-01-15T10:30:00.000Z",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-15T10:30:00.000Z"
  }
}

Update a Job

Update an existing job listing. All fields are optional.

Request:

PUT /api/jobs/507f1f77bcf86cd799439011
Content-Type: application/json

{
  "salary": 130000,
  "location": "Hybrid - New York"
}

Response:

{
  "message": "Job updated successfully",
  "data": {
    "id": "507f1f77bcf86cd799439011",
    "title": "Senior Software Developer",
    "description": "We are looking for an experienced developer...",
    "company": "Tech Corp",
    "location": "Hybrid - New York",
    "salary": 130000,
    "datePosted": "2024-01-15T10:30:00.000Z",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-15T12:00:00.000Z"
  }
}

Delete a Job

Delete a job listing.

Request:

DELETE /api/jobs/507f1f77bcf86cd799439011

Response:

{
  "message": "Job deleted successfully"
}

❌ Error Handling

The API uses consistent error response format:

{
  "error": "Error message here",
  "details": []  // Optional: validation error details
}

HTTP Status Codes

Code Description
200 Success
201 Created
400 Bad Request (validation error)
404 Not Found
429 Too Many Requests (rate limited)
500 Internal Server Error

Validation Error Example

{
  "error": "Validation failed",
  "details": [
    {
      "type": "field",
      "value": "",
      "msg": "Title is required",
      "path": "title",
      "location": "body"
    }
  ]
}

🔒 Security Features

This API implements multiple security measures:

  1. Helmet.js - Sets various HTTP headers to protect against common vulnerabilities
  2. CORS - Configurable Cross-Origin Resource Sharing
  3. Rate Limiting - Prevents abuse with configurable request limits (default: 100 requests/15 min)
  4. Input Validation - All inputs are validated and sanitized using express-validator
  5. Request Size Limiting - Body size limited to 10KB to prevent payload attacks
  6. MongoDB Injection Prevention - Mongoose ORM provides built-in protection
  7. Error Masking - Detailed errors only shown in development mode

📁 Project Structure

job-listings-api/
├── index.js              # Application entry point
├── package.json          # Project dependencies and scripts
├── .env                  # Environment variables (not in git)
├── .env.example          # Environment variables template
├── .gitignore            # Git ignore rules
├── README.md             # Project documentation
├── models/
│   └── Jobs.js           # Mongoose job schema and model
└── routes/
    └── jobs.js           # Job routes and controllers

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


📞 Support

If you encounter any issues or have questions, please open an issue in the repository.