Skip to content
Back to skills

1500 Request Building 4209185a

ASecurity

| Property | Type | Default | Description | |----------|------|---------|-------------| | `url` | `URL?` | nil | Request URL | | `httpMethod` | `String?` | "GET" | HTTP method | | `httpBody` | `Data?` | nil | Request body | | `timeoutInterval` | `TimeInterval` | 60.0 | Timeout in seconds | | `cachePolicy` | `CachePolicy` | `.useProtocolCachePolicy` | Cache behavior |

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
securityrustgoswiftapisecurityperformance

Works with

  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1500-request-building_4209185a --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1500 Request Building 4209185a?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1500 Request Building 4209185a
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1500-request-building-4209185a/badge)](https://www.skillsdirectory.com/skills/tools-only-1500-request-building-4209185a)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# URLRequest Building Reference

## Quick Reference

### URLRequest Configuration

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `url` | `URL?` | nil | Request URL |
| `httpMethod` | `String?` | "GET" | HTTP method |
| `httpBody` | `Data?` | nil | Request body |
| `timeoutInterval` | `TimeInterval` | 60.0 | Timeout in seconds |
| `cachePolicy` | `CachePolicy` | `.useProtocolCachePolicy` | Cache behavior |

### Cache Policies

| Policy | Use Case |
|--------|----------|
| `.useProtocolCachePolicy` | Default; respects server headers |
| `.reloadIgnoringLocalCacheData` | Always fetch fresh |
| `.returnCacheDataElseLoad` | Offline-first apps |
| `.returnCacheDataDontLoad` | Strictly offline |

### Content-Types

| Content Type | Use Case |
|--------------|----------|
| `application/json` | JSON body |
| `application/x-www-form-urlencoded` | Form data |
| `multipart/form-data; boundary=xxx` | File uploads |

## HTTP Headers

```swift
// Set headers
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")

// Set all at once
request.allHTTPHeaderFields = [
    "Content-Type": "application/json",
    "Accept": "application/json"
]
```

## Body Encoding

### JSON (Recommended)

```swift
struct CreateUserRequest: Encodable {
    let name: String
    let email: String
}

let body = CreateUserRequest(name: "John", email: "john@example.com")
request.httpBody = try JSONEncoder().encode(body)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
```

### Form URL Encoded

```swift
// CORRECT: Use URLComponents for proper encoding
var components = URLComponents()
components.queryItems = [
    URLQueryItem(name: "username", value: "john"),
    URLQueryItem(name: "password", value: "secret")
]
// percentEncodedQuery encodes spaces as + and handles reserved characters
request.httpBody = components.percentEncodedQuery?.data(using: .utf8)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
```

> **Warning**: Don't use `.urlQueryAllowed` for form-encoded values. It includes reserved characters (`&`, `=`, `+`, `/`, `?`) that must be escaped in parameter values. Use `URLComponents` or a custom charset with only RFC 3986 unreserved characters.

### Multipart Form Data

```swift
let boundary = UUID().uuidString
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

var body = Data()
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"image.jpg\"\r\n".data(using: .utf8)!)
body.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
body.append(imageData)
body.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
request.httpBody = body
```

## URL Query Parameters

```swift
// CORRECT: Use URLComponents
var components = URLComponents(string: "https://api.example.com/search")!
components.queryItems = [
    URLQueryItem(name: "query", value: "swift programming"),
    URLQueryItem(name: "page", value: "1")
]
let request = URLRequest(url: components.url!)

// Handle plus signs (not encoded by default)
let encodedValue = value?.replacingOccurrences(of: "+", with: "%2B")
```

## Timeout Configuration

```swift
// Request-level
var request = URLRequest(url: url)
request.timeoutInterval = 30.0

// Session-level
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 30.0   // Resets on each packet
config.timeoutIntervalForResource = 300.0 // Total time (default: 7 days!)
```

> **Note**: Per-request `timeoutInterval` only takes effect if it's not more restrictive than the session's `timeoutIntervalForRequest`. If the session enforces a stricter limit, that limit applies instead.

## Critical Anti-Patterns

### 1. CRLF Injection (CVE-2022-3918)

> **Note**: This vulnerability affects swift-corelibs-foundation versions before 5.7.3. In 5.7.3+, URLRequest rejects CR/LF in header values at the framework level. Manual sanitization is only needed for projects that cannot upgrade.

```swift
// DANGEROUS: User input in headers (affects swift-corelibs-foundation < 5.7.3)
let userInput = "value\r\nEvil-Header: injected"
request.setValue(userInput, forHTTPHeaderField: "X-Custom")

// SAFE: Sanitize header values (for pre-5.7.3 or as defense-in-depth)
let sanitized = userInput.replacingOccurrences(of: "\r", with: "")
    .replacingOccurrences(of: "\n", with: "")
request.setValue(sanitized, forHTTPHeaderField: "X-Custom")
```

### 2. Hardcoded Secrets

```swift
// DANGEROUS
request.setValue("sk_live_abc123xyz", forHTTPHeaderField: "Authorization")

// SAFE: From Keychain
let token = KeychainService.shared.getAPIToken()
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
```

### 3. Content-Type/Body Mismatch

```swift
// BUG: JSON body but wrong Content-Type
request.httpBody = try JSONEncoder().encode(user)
request.setValue("text/plain", forHTTPHeaderField: "Content-Type")

// CORRECT
request.httpBody = try JSONEncoder().encode(user)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
```

### 4. Manual URL Concatenation

```swift
// DANGEROUS: Injection risk
let url = URL(string: "https://api.com/search?q=\(userQuery)")!

// SAFE: URLComponents
var components = URLComponents(string: "https://api.com/search")!
components.queryItems = [URLQueryItem(name: "q", value: userQuery)]
```

### 5. Memory Issues with Large Files

```swift
// DANGEROUS: Loads entire file into memory
let largeFileData = try Data(contentsOf: largeFileURL)
request.httpBody = largeFileData

// SAFE: Use file-based upload
session.uploadTask(with: request, fromFile: largeFileURL)
```

### 6. Creating Sessions Per Request

```swift
// INEFFICIENT
func makeRequest() {
    let session = URLSession(configuration: .default)  // New each time!
    session.dataTask(with: request).resume()
}

// EFFICIENT: Reuse session
class NetworkManager {
    private let session = URLSession(configuration: .default)
}
```

## Review Questions

### Security
- [ ] Are header values sanitized for CRLF characters?
- [ ] Are secrets from Keychain, not hardcoded?
- [ ] Is SSL/TLS validation proper (no blanket trust)?
- [ ] Are credentials excluded from URLs and logs?

### Correctness
- [ ] Does Content-Type match body encoding?
- [ ] Is HTTP method appropriate (no body on GET)?
- [ ] Are query parameters built with URLComponents?
- [ ] Are special characters (+, ;, ,) encoded correctly?

### Performance
- [ ] Is URLSession reused across requests?
- [ ] Are timeouts configured appropriately?
- [ ] Are large uploads using file-based API?
- [ ] Is `timeoutIntervalForResource` set (not 7-day default)?

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.