Merge pull request #2 from Michilis/dev

Updates
This commit is contained in:
Michilis
2025-07-16 00:08:38 +02:00
committed by GitHub
4 changed files with 84 additions and 61 deletions

View File

@@ -176,6 +176,9 @@ Edit `.env` file:
PORT=3000
NODE_ENV=development
# API Domain/IP Configuration (for Swagger docs and CORS)
API_DOMAIN=localhost:3000
# Security Configuration
ALLOW_REDEEM_DOMAINS=ln.tips,getalby.com,wallet.mutinywallet.com
API_SECRET=your-secret-key-here
@@ -199,6 +202,34 @@ npm run dev
npm start
```
### Environment Variables
#### API_DOMAIN Configuration
The `API_DOMAIN` environment variable is used to configure the correct domain/IP for your API in production. This affects:
- **Swagger Documentation**: The "Try it out" feature will use the correct server URL
- **CORS Configuration**: Default CORS origins will use the correct protocol and domain
- **API Documentation**: Server URLs in the documentation will be accurate
**Examples:**
```bash
# Development
API_DOMAIN=localhost:3000
# Production with domain
API_DOMAIN=api.yourdomain.com
# Production with IP
API_DOMAIN=192.168.1.100:3000
# Production with custom port
API_DOMAIN=yourdomain.com:8080
```
**Note**: The protocol (http/https) is automatically determined based on `NODE_ENV`:
- `NODE_ENV=development``http://`
- `NODE_ENV=production``https://`
The API will be available at `http://localhost:3000`
## 🔧 Configuration

View File

@@ -2,10 +2,12 @@
PORT=3000
NODE_ENV=development
# API Domain/IP Configuration (for Swagger docs and CORS)
API_DOMAIN=localhost:3000
# Security Configuration
ALLOW_REDEEM_DOMAINS=*
# Default Lightning Address (used when no address is provided in redeem requests)
DEFAULT_LIGHTNING_ADDRESS=admin@your-domain.com

View File

@@ -10,23 +10,56 @@ const redemptionService = require('./services/redemption');
const app = express();
const PORT = process.env.PORT || 3000;
// Get API domain for CORS configuration
const apiDomain = process.env.API_DOMAIN || 'localhost:3000';
const isProduction = process.env.NODE_ENV === 'production';
const protocol = isProduction ? 'https' : 'http';
// Middleware
app.use(express.json({ limit: '10mb' }));
// Enhanced CORS configuration for Swagger UI
app.use(cors({
origin: process.env.ALLOWED_ORIGINS
? process.env.ALLOWED_ORIGINS.split(',').map(o => o.trim())
: ['http://localhost:3000'],
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
: [`${protocol}://${apiDomain}`],
methods: ['GET', 'POST', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'Accept', 'Origin', 'X-Requested-With'],
credentials: true,
optionsSuccessStatus: 200
}));
// Additional middleware for Swagger UI preflight requests
app.use((req, res, next) => {
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Accept, Origin, X-Requested-With');
res.status(200).end();
return;
}
next();
});
// Debug endpoint to test CORS
app.get('/api/cors-test', (req, res) => {
res.json({
success: true,
message: 'CORS test successful',
timestamp: new Date().toISOString(),
origin: req.headers.origin,
host: req.headers.host
});
});
// Swagger Documentation
app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs, {
customCss: '.swagger-ui .topbar { display: none }',
customSiteTitle: 'Cashu Redeem API Documentation',
swaggerOptions: {
filter: true,
showRequestHeaders: true
showRequestHeaders: true,
tryItOutEnabled: true
}
}));
@@ -79,52 +112,6 @@ function asyncHandler(fn) {
// API Routes
/**
* @swagger
* /:
* get:
* summary: API Information
* description: Get basic information about the Cashu Redeem API
* tags: [General]
* responses:
* 200:
* description: API information
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* example: "Cashu Redeem API"
* version:
* type: string
* example: "1.0.0"
* description:
* type: string
* example: "A production-grade API for redeeming Cashu tokens (ecash) to Lightning addresses"
* documentation:
* type: string
* example: "/docs"
* endpoints:
* type: object
* properties:
* decode:
* type: string
* example: "POST /api/decode"
* redeem:
* type: string
* example: "POST /api/redeem"
* validate:
* type: string
* example: "POST /api/validate-address"
* health:
* type: string
* example: "GET /api/health"
* github:
* type: string
* example: "https://github.com/yourusername/cashu-redeem-api"
*/
app.get('/', (req, res) => {
res.json({
name: 'Cashu Redeem API',

View File

@@ -1,5 +1,16 @@
require('dotenv').config();
const swaggerJsdoc = require('swagger-jsdoc');
// Get the API domain from environment variable, default to localhost:3000
const apiDomain = process.env.API_DOMAIN || 'localhost:3000';
const isProduction = process.env.NODE_ENV === 'production';
const protocol = isProduction ? 'https' : 'http';
// For production behind Nginx, we need to ensure the URL doesn't include the internal port
const serverUrl = isProduction
? `${protocol}://${apiDomain}`
: `${protocol}://${apiDomain}`;
const options = {
definition: {
openapi: '3.0.0',
@@ -18,12 +29,8 @@ const options = {
},
servers: [
{
url: 'http://localhost:3000',
description: 'Development server'
},
{
url: 'https://api.example.com',
description: 'Production server'
url: serverUrl,
description: isProduction ? 'Production server' : 'Development server'
}
],
components: {
@@ -323,10 +330,6 @@ const options = {
}
},
tags: [
{
name: 'General',
description: 'General API information and utilities'
},
{
name: 'Token Operations',
description: 'Operations for decoding and redeeming Cashu tokens'