# How k-skill-proxy Provides Secure Access to Korean Government APIs

> Securely access Korean government APIs with k-skill-proxy. This Fastify-based reverse proxy normalizes requests, injects auth keys, and applies rate limiting for unified access.

- Repository: [NomaDamas/k-skill](https://github.com/NomaDamas/k-skill)
- Tags: how-to-guide
- Published: 2026-08-03

---

**k-skill-proxy is a Fastify-based HTTP reverse proxy that normalizes client requests, injects authentication keys, and applies rate-limiting and caching to provide unified access to Korean public data services including AirKorea, KMA, and Seoul Open API.**

The `k-skill-proxy` package within the [NomaDamas/k-skill](https://github.com/NomaDamas/k-skill) repository eliminates the complexity of directly integrating with Korean government APIs. It handles authentication, parameter validation, and error mapping so client applications can consume public data through a single, consistent interface mounted under `/v1/<service>`.

## Configuration and Secret Isolation

On startup, the proxy builds a configuration object using `buildConfig()` defined in [`/packages/k-skill-proxy/src/server.js`](https://github.com/NomaDamas/k-skill/blob/main//packages/k-skill-proxy/src/server.js). This function extracts sensitive API keys from environment variables such as `AIR_KOREA_OPEN_API_KEY`, `KMA_OPEN_API_KEY`, and `SEOUL_OPEN_API_KEY`, keeping credentials out of source control and making the server portable across environments.

## Request Validation and Normalization

Before forwarding traffic upstream, the proxy validates incoming queries through service-specific **normalizer functions**. These guarantee that only well-formed requests reach government endpoints.

- `normalizeFineDustQuery` validates `regionHint` and `stationName` parameters for AirKorea requests in [`/packages/k-skill-proxy/src/server.js`](https://github.com/NomaDamas/k-skill/blob/main//packages/k-skill-proxy/src/server.js)
- `normalizeKmaForecastQuery` sanitizes Korean Meteorological Administration forecast parameters
- `normalizeNeisSchoolMealQuery` processes school meal queries for the NEIS system

This validation layer prevents malformed requests from consuming upstream quota or triggering errors.

## Route Whitelisting and Security

The proxy implements strict **route whitelisting** to limit attack surface. For AirKorea integration, the allowed service-operation pairs are stored in `ALLOWED_AIRKOREA_ROUTES` and verified via `isAllowedAirKoreaRoute()` before any upstream call occurs.

Additionally, the `redactSecretValue()` function scrubs API keys from upstream responses. If a government service echoes the authentication key in its payload, the proxy replaces it with `[REDACTED]` to prevent accidental leakage in logs or client responses.

## Caching and Rate Limiting

To protect upstream services and improve performance, `k-skill-proxy` implements dual protection layers:

**In-Memory Caching:** Responses are cached using `createMemoryCache()` with entries keyed by `makeCacheKey()`, which hashes the request payload. The LRU cache respects configurable TTL and size limits defined in the server configuration.

**Rate Limiting:** A per-IP token bucket algorithm implemented in `buildRateLimiter()` restricts the number of requests a single client can submit within a configurable time window, preventing abuse of expensive government API quotas.

## Upstream Integration and Proxy Logic

When a validated request passes all guards, the proxy constructs the upstream URL in functions like `proxyAirKoreaRequest()`. The implementation in [`/packages/k-skill-proxy/src/server.js`](https://github.com/NomaDamas/k-skill/blob/main//packages/k-skill-proxy/src/server.js) appends the appropriate `serviceKey` parameter and executes a `fetch` call with a 20-second timeout.

Each service module—such as [`airkorea.js`](https://github.com/NomaDamas/k-skill/blob/main/airkorea.js), [`kma-weather.js`](https://github.com/NomaDamas/k-skill/blob/main/kma-weather.js), and [`neis-school-meal.js`](https://github.com/NomaDamas/k-skill/blob/main/neis-school-meal.js)—registers its own Fastify route mounted under `/v1/<service>`. This creates clean endpoints like `GET /v1/airkorea` or `GET /v1/kma-forecast` that abstract away the underlying government API complexity.

## Response Wrapping and Error Handling

All responses are wrapped in a uniform JSON envelope containing `statusCode`, `contentType`, and the (optionally redacted) body. Error handling maps upstream failures to standard HTTP status codes:

- Missing API keys return `503 Service Unavailable` with details like `"AIR_KOREA_OPEN_API_KEY is not configured"`
- Disallowed routes return `403 Forbidden`
- Upstream timeouts or failures return `502 Bad Gateway`

## Practical Usage Examples

Call the proxy endpoints without handling API keys or complex authentication signatures:

```bash

# AirKorea real-time fine dust data

curl "http://localhost:4020/v1/airkorea?service=ArpltnInforInqireSvc&operation=getCtprvnRltmMesureDnsty&regionHint=Seoul"

```

```bash

# Korean Meteorological Administration forecast

curl "http://localhost:4020/v1/kma-forecast?nx=60&ny=127&baseDate=20240803&baseTime=0200"

```

```javascript
// NEIS school meal information using Node.js
import fetch from 'node-fetch';

const resp = await fetch(
  'http://localhost:4020/v1/neis/meal?atptOfcdcScCode=J10&sdSchulCode=7010569&mlsvYmd=20240803'
);
const data = await resp.json();
console.log(data);

```

Each request automatically receives parameter validation, API key injection, rate-limit checking, and cache lookup—completely transparent to the client.

## Summary

- **k-skill-proxy** provides a unified Fastify-based interface to Korean government APIs including AirKorea, KMA, and NEIS
- **Configuration management** via `buildConfig()` isolates API keys in environment variables
- **Security layers** include route whitelisting (`ALLOWED_AIRKOREA_ROUTES`), request normalization, and secret redaction (`redactSecretValue()`)
- **Performance protections** implement LRU caching (`createMemoryCache`) and per-IP rate limiting (`buildRateLimiter`)
- **Consistent interface** exposes all services under `/v1/<service>` endpoints with standardized error handling and response wrapping

## Frequently Asked Questions

### What government services does k-skill-proxy support?

The proxy currently wraps multiple Korean public data sources including AirKorea (environmental data), Korean Meteorological Administration (weather forecasts), Seoul Open API, Data.go.kr, NEIS (school information), and Korean legal information services. Each integration lives in its own module under `/packages/k-skill-proxy/src/`.

### How does the proxy handle API key security?

API keys are never exposed to clients. The server stores them in environment variables loaded via `buildConfig()`, injects them into upstream requests internally, and scrubs them from responses using `redactSecretValue()`. If a key is missing, the proxy returns a `503` error before attempting the upstream call.

### Can I deploy k-skill-proxy without rate limiting?

The rate limiter is configurable through environment variables during the `buildRateLimiter()` initialization. While you can adjust the token bucket settings to be permissive, removing protection entirely would require modifying the source code in [`/packages/k-skill-proxy/src/server.js`](https://github.com/NomaDamas/k-skill/blob/main//packages/k-skill-proxy/src/server.js), which is not recommended for production deployments.

### What happens when a government API is down?

The proxy implements a 20-second timeout on all upstream `fetch` calls. If the upstream fails or times out, the proxy returns a `502 Bad Gateway` or `504 Gateway Timeout` with a descriptive error message, preventing client applications from hanging indefinitely.