Skip to content

Map Rules

Map Rules let you modify traffic behavior without touching the target server. Want to serve a local JSON file instead of hitting the real API? Map Local. Want to redirect production API calls to your staging server? Map Remote. Want to change a header value or swap text in response bodies? Rewrite. All three work transparently — your application doesn’t know Ghost is modifying traffic.

This is powerful for testing: you can simulate API responses that don’t exist yet, test against different environments, inject specific error responses, or modify response data to test how your app handles edge cases — all without any code changes or server access.

Ghost supports three types of map rules, each serving a different purpose:

What this diagram shows: Every incoming request is checked against your map rules in priority order. If a rule matches, Ghost applies the corresponding action — serving a local response, redirecting to another server, or applying text replacements. If no rule matches, the request passes through normally to its original destination. Each matched flow gets tagged so you can see which rules were applied.

Serves a synthetic response without contacting the upstream server at all. The request never leaves Ghost — it’s answered locally.

Configuration fields:

FieldDescription
Status CodeThe HTTP status code to return (default: 200). Set to 404 or 500 to simulate error responses.
Content TypeThe response Content-Type header. Auto-detected from file extension if not set (e.g., .jsonapplication/json, .htmltext/html, .pngimage/png). Falls back to Go’s http.DetectContentType for unknown extensions.
File PathPath to a local file to serve as the response body. Maximum file size: 50 MB. The file must be under the ~/.ghost/ directory (path traversal with .. is blocked for security). File path takes priority over inline body — if both are set, the file is used.
BodyInline response body text. Used only when no file path is set or the file can’t be read.

The response also includes an X-Ghost-Rule header set to the rule name, so you can verify in the response headers which rule was applied.

Content type auto-detection recognizes these file extensions: .json, .xml, .html, .htm, .css, .js, .svg, .png, .jpg, .jpeg, .gif, .webp, .txt. For other extensions, Ghost sniffs the first few bytes of the file content to detect the type.

Use cases:

  • Mock an API that doesn’t exist yet — design the frontend before the backend is ready
  • Simulate errors — return a 503 response to test how your app handles server downtime
  • Serve local assets — develop UI changes by serving a local CSS or JavaScript file instead of the remote version
  • Test edge cases — return an empty array, a null field, or an extremely large response to test boundary conditions

Rewrites the request URL to redirect traffic to a different server while preserving the original path and query string. The client doesn’t know the request was rerouted — it sees the same URL it requested.

Original RequestTargetResulting Request
https://api.prod.com/v1/users?page=2https://api.staging.comhttps://api.staging.com/v1/users?page=2
https://cdn.example.com/images/logo.pnghttp://localhost:3000http://localhost:3000/images/logo.png

How it works: Ghost takes the target URL you specify, extracts just the scheme (http:// or https://) and host, and replaces the original request’s scheme and host — keeping the path, query parameters, and everything else intact. The Host header is also updated to match the new target.

Use cases:

  • Route to staging — redirect production API calls to a staging server to test integration
  • Test against localhost — point mobile app traffic to your local development server
  • Switch API versions — redirect from one API host to another without changing the client code
  • Load balancing testing — redirect traffic to a specific backend server

Applies regex find-and-replace on request or response data. Unlike Map Local and Map Remote which change the destination, Rewrite modifies the content while the request still goes to the original server.

Configuration fields:

FieldDescription
PhaseWhen to apply the replacement: request (before the request is sent to the server) or response (after the response comes back)
TargetWhat to rewrite: url (the request URL), body (the request or response body depending on phase), or header:<name> (a specific header value, e.g., header:Authorization)
FindThe search pattern. Supports two modes: plain text (exact string match — special regex characters are auto-escaped) or regex (full Go regular expression syntax). Toggle between modes in the UI.
ReplaceThe replacement string. Supports backreferences ($1, $2, etc.) that insert captured groups from the regex pattern.

Examples:

PhaseTargetFindReplaceWhat It Does
requesturl/v1//v2/Upgrades API version in the URL
requestheader:AuthorizationBearer old-tokenBearer new-tokenSwaps the auth token on every request
responsebody"debug":\s*true"debug": falseStrips debug flags from JSON responses
requestheader:Accept-LanguageentrChanges the language preference to Turkish
responsebody"price":(\d+)"price":0Sets all prices to zero for testing free-tier display

When rewriting headers, Ghost iterates through all values of the named header (HTTP headers can have multiple values), applies the regex replacement to each, and updates the header. When rewriting the body, the Content-Length is automatically updated to reflect the new size.

The regex engine is Go’s standard regexp package — the compiled regex is cached per rule (thread-safe with a mutex) for performance, and invalidated when the pattern changes.

The UI includes a “Test & Edit” feature for regex mode — type your pattern and replacement, and see the result before the rule is applied to live traffic.

Rules match incoming requests using three criteria — all three must match for a rule to apply:

CriteriaMatch TypePattern SyntaxExample PatternWhat It Matches
HostGlob (path.Match)* matches any sequence of characters within a path segment, ? matches any single character, [abc] matches character classes*.example.comapi.example.com, cdn.example.com, www.example.com
PathGlob (path.Match)Same glob syntax as host/api/v1/*/api/v1/users, /api/v1/products, /api/v1/orders
MethodExact (case-insensitive)HTTP method or empty for “any”POSTOnly POST requests. Leave empty to match all methods.

Empty patterns match everything. If you leave the host pattern empty, the rule matches any host. Leave all three empty and the rule matches all traffic.

Important: The * glob only matches within a single path segment (separated by /). To match nested paths, you’d need multiple segments: /api/*/users/* matches /api/v1/users/123 but /api/* only matches /api/anything (one level deep, not /api/v1/users).

Every rule has a priority number (integer). Lower numbers run first.

The behavior differs by rule type:

Rule TypeEvaluation StrategyWhat It Means
Map LocalFirst match wins (short-circuit)Ghost checks enabled Map Local rules in priority order and uses the first one that matches. Other Map Local rules for the same request are skipped.
Map RemoteFirst match wins (short-circuit)Same as Map Local — the first matching enabled remote rule is used.
RewriteAll matches apply (cumulative)Every matching enabled rewrite rule is applied in priority order. Multiple rewrite rules can modify the same request/response.

When priorities are equal, rules are sorted by their insertion order (the order they were created).

Map Rules run early in Ghost’s interceptor pipeline — second in the chain:

Breakpoints → Map Rules → Addons → Storage → Security

This order matters:

  • Map Local short-circuits the pipeline for response — the proxy never contacts the upstream server. The synthetic response still passes through downstream interceptors (Addons, Storage, Security), so addons can tag it and it gets stored in the database.
  • Map Remote rewrites the URL before the proxy connects to the upstream, so the connection goes to the new target.
  • Rewrite modifications on the request happen before addons and storage see it, so modified URLs and bodies are what get recorded.
  • Breakpoints run before Map Rules, so you can pause and inspect a request before any map rule applies.

When a rule matches, Ghost adds metadata to the flow so you can see what happened:

TagMeaning
map-localThe response was served locally (the request never reached the real server)
map-remoteThe request URL was rewritten to a different target server
rewriteA regex replacement was applied to the request or response

Additional metadata fields:

  • map_rule — the name of the rule that matched (for Map Local and Map Remote)
  • map_remote_target — the redirect destination URL (for Map Remote)
  • rewrite_rule — the name of the rewrite rule (for Rewrite)

These tags are searchable via GQL: tag:map-local shows all flows served locally, tag:rewrite shows all modified flows.

The rules panel opens as a slide-over from the toolbar (Ctrl+3). It has two views:

Shows all map rules as cards, each displaying:

  • Type icon — color-coded: green for Local, cyan for Remote, purple for Rewrite
  • Rule name — the display label you gave the rule
  • Type badge — “Local”, “Remote”, or “Rewrite”
  • Pattern display — shows the method, host, and path patterns (e.g., “POST .api.com /checkout/”)
  • Hover actions — toggle enable/disable and delete button

An “Add” button in the header creates a new rule.

When you click a rule or create a new one, a step-by-step editor opens:

Step 1: “What should Ghost do?” — Select the rule type by clicking one of three cards:

  • Map Local (green) — “Serve a local response”
  • Map Remote (cyan) — “Redirect to another server”
  • Rewrite (purple) — “Find and replace content”

Step 2: “Match requests where…” — Configure when this rule should activate:

  • Rule name (for your reference)
  • Host pattern (glob)
  • Path pattern (glob)
  • Method (dropdown: Any, GET, POST, PUT, DELETE, PATCH)
  • Priority number

Step 3: Type-specific configuration (varies by rule type — see the fields described above for each type).

Actions footer: Enable/disable toggle, Cancel, and Save buttons.

Map rules are stored in SQLite (map_rules table with 17 data fields). Changes are applied immediately to the in-memory rule manager — no proxy restart needed. The rule set is reloaded from the database on Ghost startup.

Rule changes are broadcast to all connected frontends in real-time:

EventWhen It Fires
rule.createdA new rule was saved — includes the full rule data
rule.updatedA rule was modified or toggled — includes the updated rule data
rule.deletedA rule was removed — includes only the rule ID
MethodEndpointDescription
GET/api/v1/rulesList all map rules, sorted by priority
POST/api/v1/rulesCreate a new rule
GET/api/v1/rules/{id}Get a single rule by ID
PUT/api/v1/rules/{id}Update a rule (name, patterns, type-specific fields)
DELETE/api/v1/rules/{id}Delete a rule
POST/api/v1/rules/{id}/toggleToggle a rule’s enabled state without changing anything else