Skip to content

What is an HTTP Rule?

An HTTP rule in Thymian applies the familiar concept of linting—like ESLint for JavaScript—to HTTP APIs. Rules validate that your API follows HTTP specifications, industry best practices, or your organization’s guidelines.

Unlike tools that only validate static OpenAPI documents (like Spectral), Thymian rules work across three contexts:

  • Lint — Checks API specifications before implementation
  • Test — Actively tests running API endpoints
  • Analyze — Validates recorded HTTP transactions

This multi-context approach prevents API drift and ensures governance throughout the development lifecycle.

Every HTTP rule consists of several components:

httpRule('rule-name')
.severity('error') // How critical is this rule?
.type('static', 'test') // Where does it run?
.description('...') // What does it validate?
.appliesTo('server') // Who must comply?
.rule((ctx) => { ...
}) // How to validate?
.done();
ComponentPurposeExample
NameUnique identifier'no-body-in-get-requests'
SeverityImpact level'error', 'warn', 'hint'
TypeValidation contexts'static', 'analytics', 'test', 'informational'
DescriptionWhat the rule validates'GET requests should not include a body'
Applies ToTarget participant'client', 'server', 'proxy'
Validation LogicHow to check complianceFilter expressions or custom functions
URL (optional)Reference documentationRFC section or internal docs

Thymian provides three distinct contexts for running rules, each suited for different development stages:

flowchart TB
  subgraph Design["📐 Design Phase"]
    A[OpenAPI Spec] --> B[Lint Context]
    B --> C[Validates Spec Definitions]
  end

  subgraph Development["💻 Development Phase"]
    D[Running API] --> E[Test Context]
    E --> F[Generates & Runs Tests]
  end

  subgraph Production["🔍 Production Phase"]
    G[Recorded Traffic] --> H[Analyze Context]
    H --> I[Analyzes Transactions]
  end

  C --> J[Reports]
  F --> J
  I --> J

What it validates: API specifications (e.g. OpenAPI documents)

When to use: During design and development to catch issues early

Advantages:

  • Very fast (no network calls)
  • Immediate feedback during development
  • Prevents issues before implementation

Example:

// Validates that paginated responses define Link header in the spec
.
type('static')
.rule((ctx) =>
ctx.validateCommonHttpTransactions(
and(statusCode(200), path('/api/*/list')),
not(responseHeader('link'))
)
)

What it validates: Live API endpoints

When to use: During integration testing and CI/CD pipelines

Advantages:

  • Tests actual implementation
  • Discovers runtime issues
  • Validates server behavior

Example:

// Actively tests that servers support both GET and HEAD methods
.
type('test')
.rule((ctx) =>
ctx.validateCommonHttpTransactions(
method('GET'),
statusCode(501) // Not Implemented
)
)

What it validates: Recorded HTTP transactions

When to use: For production monitoring and traffic analysis

Advantages:

  • Validates real-world usage
  • No impact on running services
  • Discovers issues from actual traffic

Example:

// Analyzes recorded traffic for missing authentication headers
.
type('analytics')
.rule((ctx) =>
ctx.validateCommonHttpTransactions(
statusCode(401),
not(responseHeader('www-authenticate'))
)
)
FeatureLintTestAnalyze
Speed⚡ Very Fast⏱️ Variable*⚡ Fast
Data SourceOpenAPI specLive APIRecorded traffic
Network CallsNoYesNo
When to RunDesign & devCI/CD & devProduction & QA
CatchesSpec issuesImplementation issuesReal-world issues
CoverageAll defined endpointsTested endpointsUsed endpoints

*Test speed depends on API endpoint performance and network conditions

To simplify rule development, Thymian provides a common interface that works across all three contexts:

httpRule('works-everywhere')
.type('static', 'analytics', 'test') // Same rule, three contexts
.rule((ctx) => ctx.validateCommonHttpTransactions(statusCode(500), not(responseHeader('content-type'))))
.done();

This rule automatically:

  • Validates spec definitions in lint mode
  • Tests live endpoints in test mode
  • Analyzes recorded traffic in analyze mode

You write the logic once, and Thymian adapts it to each context.

Rules can include additional metadata for documentation and organization:

httpRule('comprehensive-rule').severity('error').type('static', 'analytics').url('https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.1').description('500 responses must include Content-Type header').summary('Missing Content-Type on 500 errors').tags('errors', 'headers', 'http-semantics').appliesTo('server', 'proxy').done();

Use cases for metadata:

  • url — Link to specifications or internal documentation
  • summary — Short description for search and listings
  • tags — Categorize rules for filtering
  • appliesTo — Clarify who must follow the rule

Rules have three severity levels that indicate their importance:

SeverityWhen to UseExample
errorMust comply (MUST/MUST NOT in specs)'401 must include WWW-Authenticate'
warnShould comply (SHOULD/SHOULD NOT in specs)'POST should return 201 for created resources'
hintOptional (MAY in specs)'Consider adding Cache-Control headers'

Note: Rules that describe requirements which cannot be tested automatically can use the 'informational' rule type (see The Three Validation Contexts). This is separate from the severity level.

// Critical requirement
.
severity('error')
// Recommended practice
.severity('warn')
// Optional suggestion
.severity('hint')
// Informational rule
.severity('informational')

One of the most powerful features is using the same rule in multiple contexts:

httpRule('consistent-error-responses')
.severity('error')
.type('static', 'test') // Both design and implementation
.description('Error responses must include problem details')
.rule((ctx) => ctx.validateCommonHttpTransactions(statusCodeRange(400, 599), not(responseMediaType('application/problem+json'))))
.done();

This rule ensures:

  1. Your spec defines proper error responses (lint)
  2. Your implementation actually returns them (test)

If they diverge, violations are reported in one context or the other.

Now that you understand what HTTP rules are and how they work: