Skip to content

Commit db64f72

Browse files
committed
feat: Add configurable local-only middleware for consistency with other services
- Added DISABLE_LOCAL_ONLY config option to allow external access when needed - Made localOnlyMiddleware conditional based on config.disableLocalOnly - Updated .env.example with new configuration option - Maintains secure-by-default behavior (localhost only unless explicitly disabled) - Consistent with school district service architecture
1 parent a6e48de commit db64f72

File tree

4 files changed

+120
-39
lines changed

4 files changed

+120
-39
lines changed

.env.example

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,10 @@ GOOGLE_MAPS_API_KEY=your_google_maps_api_key_here
99

1010
# Server Configuration (optional)
1111
PORT=3715
12-
NODE_ENV=development
12+
NODE_ENV=development
13+
14+
# Access Control
15+
# Set to true to disable local-only restriction and allow external access
16+
# WARNING: Only set to true if you have other security measures in place!
17+
# DEFAULT: false (only localhost can access the API)
18+
DISABLE_LOCAL_ONLY=false

README.md

Lines changed: 107 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@ High-performance address validation and geocoding service using USPS and Google
66

77
Provides address standardization and geocoding for the CandyComp platform. Combines USPS official address validation with Google Maps geocoding for accurate property location data. Built with TypeScript and Express, featuring token caching and optimized for real estate applications.
88

9-
## Quick Start
9+
## Features
10+
11+
- **USPS Integration** - Official USPS Web Tools API for address standardization
12+
- **Google Maps Geocoding** - Forward and reverse geocoding
13+
- **Token Management** - Automatic USPS OAuth token refresh
14+
- **IP Restriction** - Security through IP whitelisting
15+
- **Response Caching** - In-memory caching for duplicate requests
16+
- **TypeScript** - Full type safety with zero errors/warnings
17+
18+
## Installation
1019

1120
```bash
1221
# Install dependencies
@@ -16,34 +25,34 @@ npm install
1625
cp .env.example .env
1726
# Edit .env with your API credentials
1827

28+
# Build TypeScript
29+
npm run build
30+
1931
# Run development server
2032
npm run dev
2133

2234
# Run production
2335
npm start
2436
```
2537

26-
## Configuration
27-
28-
Required environment variables:
29-
30-
| Variable | Description | Example |
31-
| --------------------- | ---------------------------- | ---------------- |
32-
| `PORT` | Service port | `3715` |
33-
| `USPS_CLIENT_ID` | USPS Web Tools Client ID | `your-client-id` |
34-
| `USPS_CLIENT_SECRET` | USPS Web Tools Client Secret | `your-secret` |
35-
| `GOOGLE_MAPS_API_KEY` | Google Maps API key | `AIza...` |
36-
| `ALLOWED_IPS` | Comma-separated allowed IPs | `::1,127.0.0.1` |
38+
## Environment Variables
3739

38-
## API Reference
40+
| Variable | Description | Example |
41+
| ------------------- | ---------------------------- | -------------- |
42+
| PORT | Service port | 3715 |
43+
| USPS_CLIENT_ID | USPS Web Tools Client ID | your-client-id |
44+
| USPS_CLIENT_SECRET | USPS Web Tools Client Secret | your-secret |
45+
| GOOGLE_MAPS_API_KEY | Google Maps API key | AIza... |
46+
| ALLOWED_IPS | Comma-separated allowed IPs | ::1,127.0.0.1 |
47+
| NODE_ENV | Environment mode | production |
3948

40-
### Endpoints
49+
## API Endpoints
4150

42-
#### `POST /validate`
51+
### `POST /validate`
4352

4453
Validate and standardize an address
4554

46-
**Request Body:**
55+
**Request:**
4756

4857
```json
4958
{
@@ -72,11 +81,11 @@ Validate and standardize an address
7281
}
7382
```
7483

75-
#### `POST /geocode`
84+
### `POST /geocode`
7685

7786
Forward geocode an address
7887

79-
**Request Body:**
88+
**Request:**
8089

8190
```json
8291
{
@@ -95,11 +104,11 @@ Forward geocode an address
95104
}
96105
```
97106

98-
#### `POST /reverse-geocode`
107+
### `POST /reverse-geocode`
99108

100109
Get address from coordinates
101110

102-
**Request Body:**
111+
**Request:**
103112

104113
```json
105114
{
@@ -120,7 +129,7 @@ Get address from coordinates
120129
}
121130
```
122131

123-
#### `GET /health`
132+
### `GET /health`
124133

125134
Health check endpoint
126135

@@ -135,9 +144,14 @@ npm run type-check
135144

136145
# Linting
137146
npm run lint
147+
npm run lint:fix
138148

139149
# Format code
140150
npm run format
151+
npm run format:check
152+
153+
# Clean build
154+
npm run clean
141155
```
142156

143157
## Testing
@@ -155,15 +169,6 @@ npm run test:watch
155169

156170
## Architecture
157171

158-
### Key Features
159-
160-
- **USPS Integration**: Official USPS Web Tools API for address standardization
161-
- **Google Maps API**: Geocoding and reverse geocoding
162-
- **Token Management**: Automatic USPS OAuth token refresh
163-
- **IP Restriction**: Security through IP whitelisting
164-
- **Error Handling**: Comprehensive error handling with fallbacks
165-
- **Response Caching**: In-memory caching for duplicate requests
166-
167172
### Service Flow
168173

169174
1. Receive address validation request
@@ -172,19 +177,85 @@ npm run test:watch
172177
4. Geocode through Google Maps
173178
5. Return standardized address with coordinates
174179

175-
## Deployment
180+
### Key Components
181+
182+
- **USPS Client** - Handles OAuth token management and API calls
183+
- **Google Maps Client** - Geocoding and reverse geocoding
184+
- **Cache Manager** - In-memory caching for performance
185+
- **IP Middleware** - Security through IP whitelisting
186+
- **Error Handler** - Comprehensive error handling with fallbacks
176187

177-
Runs as a local service on port 3715:
188+
## Production Deployment
189+
190+
### Using PM2
178191

179192
```bash
180-
# Start service
181-
npm start
193+
# Build for production
194+
npm run build
182195

183-
# Using PM2
196+
# Start with PM2
184197
pm2 start ecosystem.config.js
185-
pm2 logs address-validation-service
198+
199+
# Monitor
200+
pm2 monit
201+
202+
# View logs
203+
pm2 logs service-address-validation
204+
205+
# Restart
206+
pm2 restart service-address-validation
186207
```
187208

209+
### Manual Start
210+
211+
```bash
212+
npm start
213+
```
214+
215+
## GitHub Actions Deployment
216+
217+
The repository includes a GitHub Actions workflow that automatically builds and deploys the service when you push to the `main` branch.
218+
219+
### Required GitHub Secrets
220+
221+
Configure these secrets in your GitHub repository settings:
222+
223+
#### SSH Connection
224+
225+
- `LINODE_HOST` - Server IP or hostname
226+
- `LINODE_USERNAME` - SSH username (e.g., `puppeteer-user`)
227+
- `LINODE_PASSWORD` - SSH password for authentication
228+
229+
#### Application Environment
230+
231+
- `USPS_CLIENT_ID` - USPS Web Tools Client ID
232+
- `USPS_CLIENT_SECRET` - USPS Web Tools Client Secret
233+
- `GOOGLE_MAPS_API_KEY` - Google Maps API key
234+
- `ALLOWED_IPS` - Comma-separated allowed IPs
235+
- `NODE_ENV` - Environment setting (e.g., `production`)
236+
237+
### Deployment Process
238+
239+
1. Builds TypeScript project
240+
2. Copies built files to server
241+
3. Creates `.env` file from GitHub secrets
242+
4. Installs production dependencies
243+
5. Restarts PM2 process
244+
245+
## Performance
246+
247+
- **Caching** - In-memory cache for duplicate requests
248+
- **Token Reuse** - USPS OAuth tokens cached until expiry
249+
- **Connection Pooling** - Optimized HTTP connections
250+
- **Async Processing** - Non-blocking operations
251+
252+
## Security
253+
254+
- **IP Whitelisting** - Only configured IPs can access
255+
- **Input Validation** - All inputs validated before processing
256+
- **Error Sanitization** - Sensitive data removed from error responses
257+
- **Rate Limiting** - Built-in request throttling
258+
188259
## License
189260

190261
© 2024 Waleed Judah. All rights reserved.

src/config/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface Config {
1111
// Server
1212
port: number;
1313
nodeEnv: string;
14+
disableLocalOnly: boolean;
1415

1516
// USPS API
1617
usps: {
@@ -63,6 +64,7 @@ function validateConfig(): Config {
6364
return {
6465
port: parseInt(process.env['PORT'] || '3715', 10),
6566
nodeEnv: process.env['NODE_ENV'] || 'development',
67+
disableLocalOnly: process.env['DISABLE_LOCAL_ONLY'] === 'true',
6668

6769
usps: {
6870
tokenUrl: process.env['USPS_TOKEN_URL']!,

src/server.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -870,8 +870,10 @@ if (config.nodeEnv === 'production' || process.env['ENABLE_SECURITY'] === 'true'
870870
app.use(...securityMiddleware());
871871
}
872872

873-
// Local only middleware
874-
app.use(localOnlyMiddleware);
873+
// Apply local-only middleware for actual API endpoints (unless disabled)
874+
if (!config.disableLocalOnly) {
875+
app.use(localOnlyMiddleware);
876+
}
875877

876878
// Cache stats endpoint
877879
app.get('/cache/stats', (_req: Request, res: Response) => {

0 commit comments

Comments
 (0)