Skip to content

HTTP Methods Reference — Swift source

A searchable reference for every HTTP request method - GET, POST, PUT, PATCH, DELETE, and more. See at a glance which are safe, idempotent, and cacheable, then compare any two methods side by side.

This is the Swift implementation — the same logic the interactive tool runs, in a shareable, citable form.

// Source: swift.swift
// Language: Swift (Swift 5.9, standard library only — no Foundation)
//
// HTTP request-method reference — pure, deterministic data + lookups.
//
// CosmoDev polyglot showcase port of the `http-methods` tool, ported from
// src/lib/http-methods.ts. Functionally equivalent to the TypeScript original:
// identical inputs yield identical outputs (case-insensitive lookup, flag +
// free-text filtering, and a human-readable semantic comparison report).
//
// Property flags (safe / idempotent / cacheable / hasBody) follow RFC 9110
// and the MDN reference table.
//
// License: display source — part of CosmoDev's polyglot tool pages.

/// HTTP request-method reference — pure data + lookups.
///
/// A caseless `enum` is the idiomatic Swift namespace: it cannot be
/// instantiated, so it just groups the canonical table and its helpers.
enum HttpMethods {
    /// One HTTP request method and its semantic properties.
    struct MethodEntry: Equatable {
        let method: String       // Uppercase method name, e.g. "GET".
        /// Read-only semantics — no server state change.
        let safe: Bool
        /// Repeating the call has the same effect as a single call.
        let idempotent: Bool
        /// Responses may be stored by a cache (RFC 9110 / MDN).
        let cacheable: Bool
        /// The method conventionally carries a request body.
        let hasBody: Bool
        let description: String
        let typicalUse: String
    }

    /// The nine HTTP request methods (RFC 9110 / 9111), in canonical order.
    ///
    /// A `let` array — the single source of truth the helpers hand out
    /// references into.
    static let methods: [MethodEntry] = [
        MethodEntry(
            method: "GET",
            safe: true, idempotent: true, cacheable: true, hasBody: false,
            description: "Retrieves a representation of the target resource; a read-only request.",
            typicalUse: "Fetching a web page, reading an API resource, loading an image."
        ),
        MethodEntry(
            method: "POST",
            safe: false, idempotent: false, cacheable: true, hasBody: true,
            description: "Submits data to be processed, typically creating a new resource or triggering an action.",
            typicalUse: "Submitting a form, creating a record, publishing a message."
        ),
        MethodEntry(
            method: "PUT",
            safe: false, idempotent: true, cacheable: false, hasBody: true,
            description: "Replaces the target resource entirely with the request body.",
            typicalUse: "Updating a full record at a known URL, uploading a file by its path."
        ),
        MethodEntry(
            method: "PATCH",
            safe: false, idempotent: false, cacheable: false, hasBody: true,
            description: "Applies a partial modification to the target resource.",
            typicalUse: "Updating one field of a record, toggling a flag."
        ),
        MethodEntry(
            method: "DELETE",
            safe: false, idempotent: true, cacheable: false, hasBody: false,
            description: "Removes the target resource.",
            typicalUse: "Deleting a record or file by its URL."
        ),
        MethodEntry(
            method: "HEAD",
            safe: true, idempotent: true, cacheable: true, hasBody: false,
            description: "Identical to GET but returns only the response headers, no body.",
            typicalUse: "Checking existence, size, or freshness before downloading."
        ),
        MethodEntry(
            method: "OPTIONS",
            safe: true, idempotent: true, cacheable: false, hasBody: false,
            description: "Describes the communication options for the target resource.",
            typicalUse: "CORS preflight requests, discovering allowed methods."
        ),
        MethodEntry(
            method: "CONNECT",
            safe: false, idempotent: false, cacheable: false, hasBody: false,
            description: "Establishes a tunnel to the server (used with TLS/HTTPS proxies).",
            typicalUse: "Proxying encrypted connections through an intermediary."
        ),
        MethodEntry(
            method: "TRACE",
            safe: true, idempotent: true, cacheable: false, hasBody: false,
            description: "Performs a message loop-back test along the path to the target (debugging only).",
            typicalUse: "Diagnosing request transformations by intermediaries."
        ),
    ]

    /// Filter options. Each boolean is `Bool?` so callers can distinguish
    /// "constrain to `false`" from "no constraint" (`nil`) — a tri-state a
    /// bare `Bool` cannot express.
    struct MethodFilter {
        var safe: Bool? = nil
        var idempotent: Bool? = nil
        var cacheable: Bool? = nil
        /// Free text matched case-insensitively against method, description,
        /// and typicalUse. Ignored when empty after trimming.
        var query: String? = nil
    }

    /// Semantic diff between two methods.
    struct MethodComparison: Equatable {
        /// Both methods share the `safe` flag.
        let sameSafety: Bool
        /// Both methods share the `idempotent` flag.
        let sameIdempotence: Bool
        /// One sentence per mismatched property (safe, idempotent, cacheable, hasBody).
        let differences: [String]
    }

    /// Case-insensitive single-method lookup.
    ///
    /// Returns the canonical entry, or `nil` when unknown — the Swift
    /// analogue of TS's `MethodEntry | null`.
    static func getMethod(_ name: String) -> MethodEntry? {
        // ASCII method names: uppercased() is locale-invariant and matches
        // the TypeScript original for the alphabetic tokens.
        let n = trim(name).uppercased()
        return methods.first { $0.method == n }
    }

    /// Returns the methods satisfying every present flag and, when `query`
    /// is non-empty after trimming, matching it in at least one of
    /// {method, description, typicalUse}.
    static func filterMethods(_ opts: MethodFilter = MethodFilter()) -> [MethodEntry] {
        let q = trim(opts.query ?? "").lowercased()

        return methods.filter { m in
            // Each present flag is an AND constraint; nil means skip.
            if let wantSafe = opts.safe, m.safe != wantSafe { return false }
            if let wantIdempotent = opts.idempotent, m.idempotent != wantIdempotent { return false }
            if let wantCacheable = opts.cacheable, m.cacheable != wantCacheable { return false }

            guard !q.isEmpty else { return true }
            return m.method.lowercased().contains(q)
                || m.description.lowercased().contains(q)
                || m.typicalUse.lowercased().contains(q)
        }
    }

    /// Surfaces where two methods' semantics agree and differ.
    ///
    /// `differences` lists every mismatched property (safe, idempotent,
    /// cacheable, hasBody) as a human-readable sentence, reproducing the
    /// canonical phrasing verbatim so output stays identical to the
    /// TypeScript original and the other polyglot ports.
    static func compareMethods(_ a: MethodEntry, _ b: MethodEntry) -> MethodComparison {
        var differences: [String] = []

        if a.safe != b.safe {
            differences.append("\(a.method) is \(safeWord(a.safe)), \(b.method) is \(safeWord(b.safe)).")
        }
        if a.idempotent != b.idempotent {
            differences.append("\(a.method) is \(idempotentWord(a.idempotent)), \(b.method) is \(idempotentWord(b.idempotent)).")
        }
        if a.cacheable != b.cacheable {
            differences.append("\(a.method) is \(cacheableWord(a.cacheable)), \(b.method) is \(cacheableWord(b.cacheable)).")
        }
        if a.hasBody != b.hasBody {
            differences.append("\(a.method) \(bodyWord(a.hasBody)), \(b.method) \(bodyWord(b.hasBody)).")
        }

        return MethodComparison(
            sameSafety: a.safe == b.safe,
            sameIdempotence: a.idempotent == b.idempotent,
            differences: differences
        )
    }

    /// Trims whitespace from both ends. Hand-rolled on `Character.isWhitespace`
    /// so the port needs no Foundation import.
    private static func trim(_ s: String) -> String {
        var view = Substring(s)
        while let first = view.first, first.isWhitespace { view = view.dropFirst() }
        while let last = view.last, last.isWhitespace { view = view.dropLast() }
        return String(view)
    }

    // Phrasing helpers keep the difference-sentence wording in one place, so
    // the output stays in lock-step across every polyglot port.
    private static func safeWord(_ v: Bool) -> String {
        v ? "safe" : "not safe"
    }

    private static func idempotentWord(_ v: Bool) -> String {
        v ? "idempotent" : "not idempotent"
    }

    private static func cacheableWord(_ v: Bool) -> String {
        v ? "cacheable" : "not cacheable"
    }

    private static func bodyWord(_ v: Bool) -> String {
        v ? "takes a body" : "does not take a body"
    }
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →