A robust, scalable, and secure GraphQL API built with PHP, MySQL, and Redis. This project leverages Docker for containerization, providing a seamless development and deployment experience. Key features include JWT-based authentication, comprehensive rate limiting, and support for dynamic queries across multiple database tables. The API dynamically exposes services based on the RDBMS database and table structures, making it highly adaptable and flexible.
- GraphQL API: Leverage the power of GraphQL for efficient data querying and mutation.
- JWT Authentication: Secure your API with JSON Web Tokens, ensuring that only authenticated users can access your endpoints.
- Rate Limiting: Prevent abuse by limiting the number of requests per user within a specified timeframe using Redis.
- Dynamic Querying: Automatically generate queries for all available database tables, making your API flexible and powerful.
- Dockerized Setup: Easily set up and run your application using Docker and Docker Compose, ensuring a consistent development environment.
- High Performance: Optimized for performance with caching and efficient database querying.
- Security: Protect your API endpoints with JWT authentication.
- Scalability: Built to handle a large number of requests with rate limiting.
- Flexibility: Supports dynamic querying, making it adaptable to various use cases.
- Ease of Use: Simple setup and deployment with Docker.
- Community and Support: Join a growing community of developers and gain support through GitHub Issues and Pull Requests.
- Overview
- Architecture
- Prerequisites
- Setup
- Configuration
- Running the Service
- JWT Token Handling
- Rate Limiting
- Pagination
- API Usage
- Troubleshooting
- License
This project provides a GraphQL API for interacting with a MySQL database. The API includes JWT-based authentication and rate limiting to ensure secure and efficient access. It leverages Docker for containerization, ensuring an easy setup and deployment process.
The architecture consists of the following components:
- MySQL Database: Stores the data for various entities.
- Redis: Used for rate limiting to manage API request rates.
- PHP-FPM with Apache: Hosts the GraphQL API and handles requests.
- Docker Compose: Manages the containerized environment, making it easy to set up and run the entire stack.
- Database.php: Handles database interactions.
- GraphQLSchema.php: Defines the GraphQL schema and resolvers.
- JwtHandler.php: Manages JWT token creation and validation.
- RateLimiter.php: Implements rate limiting using Redis.
- api.php: Entry point for handling GraphQL requests with JWT authentication and rate limiting.
- Docker
- Docker Compose
-
Clone the repository:
git clone https://github.com/yourusername/graphql-mysql-class.git cd graphql-mysql-class
-
Build and start the Docker containers:
docker-compose up -d --build
The configuration is managed through the config.php
file. It includes settings for the MySQL database, JWT secret, and other relevant configurations.
<?php
return [
'db' => [
'host' => 'db',
'user' => 'myuser',
'password' => 'mypassword',
'database' => 'mydatabase',
],
'jwt_secret' => 'your_jwt_secret',
];
-
Start the containers:
docker-compose up -d --build
-
Generate a JWT token:
Access the endpoint to generate a token:
curl http://localhost/GenerateToken.php
Copy the token from the response.
-
Make requests to the GraphQL endpoint:
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer your-jwt-token" --data '{ "query": "{ products(page: 1) { products { productCode, productName }, total, page, token } }" }' http://localhost/api.php
curl --location 'http://localhost/api.php' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwiaWF0IjoxNzE5NTk3MTU0LCJuYmYiOjE3MTk1OTcxNTQsInN1YiI6InVzZXIxMjMifQ.paf6YFnETH10TOGqZ5MKvOkZc1T6gIEwjL3tspXdgGI' \ --data '{"query":"{ customers(page: 1) { customers { customerNumber, customerName, phone }, total, page, token } }","variables":{}}'
The JWT tokens are used to authenticate API requests. The JwtHandler.php
file handles the creation and validation of these tokens.
<?php
require 'JwtHandler.php';
$jwtHandler = new MyApp\JwtHandler('your_jwt_secret');
$token = $jwtHandler->encode(['sub' => 'user123']);
echo $token;
The token is validated in api.php
by decoding it and checking its validity.
Rate limiting is implemented using Redis to ensure that each user cannot exceed a defined number of requests per second.
Rate limiting helps to protect your API from abuse and ensures fair usage among users. It prevents a single user from overwhelming the system, thus maintaining the performance and availability of the API for all users.
We use Redis to store and manage the request counts for each user. The rate limiter checks the number of requests made by a user within a specified time window and allows or blocks the request based on the configured limits.
<?php
namespace MyApp;
class RateLimiter {
private $redis;
private $maxRequests;
private $windowSeconds;
public function __construct($host, $maxRequests, $windowSeconds) {
$this->redis = new \Redis();
$this->redis->connect($host);
$this->maxRequests = $maxRequests;
$this->windowSeconds = $windowSeconds;
}
public function isRateLimited($key, $service) {
$redisKey = "ratelimit:{$service}:{$key}";
$current = $this->redis->incr($redisKey);
if ($current == 1) {
$this->redis->expire($redisKey, $this->windowSeconds);
}
if ($current > $this->maxRequests) {
error_log("Rate limit exceeded for key: $redisKey");
return true;
}
error_log("Current count for key $redisKey: $current");
return false;
}
}
Pagination is essential for managing large datasets by breaking them down into smaller, more manageable chunks. This improves performance and usability by allowing users to fetch data page by page.
- Performance: Reduces the load on the server and database by limiting the amount of data processed and sent over the network.
- User Experience: Improves the user experience by providing data in smaller, more digestible chunks.
- Scalability: Enables the API to handle large datasets efficiently.
We implement pagination using page numbers and a fixed page size. The client specifies the page number and the number of items per page, and the server returns the corresponding subset of data.
{
products(page: 1) {
products {
productCode
productName
}
total
page
token
}
}
{
products(page: 1) {
products {
productCode
productName
}
total
page
token
}
}
{
customers(page: 1) {
customers {
customerNumber
customerName
phone
}
total
page
token
}
}
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer your-jwt-token" --data '{ "query": "{ products(page: 1) { products { productCode, productName }, total, page, token } }" }' http://localhost/api.php
curl --location 'http://localhost/api.php' \
--header 'Content-Type
: application/json' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwiaWF0IjoxNzE5NTk3MTU0LCJuYmYiOjE3MTk1OTcxNTQsInN1YiI6InVzZXIxMjMifQ.paf6YFnETH10TOGqZ5MKvOkZc1T6gIEwjL3tspXdgGI' \
--data '{"query":"{ customers(page: 1) { customers { customerNumber, customerName, phone }, total, page, token } }","variables":{}}'
- Docker Issues: Ensure Docker and Docker Compose are installed and running.
- Redis Connection: Verify that Redis is running and accessible.
- JWT Token Issues: Ensure the token is correctly generated and included in the request headers.