Back to skills
SKILL.md
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
Works with
Security analysis
100/100npx -y skills add tools-only/X-Skills --skill 1500-request-building_4209185a --agent claude-codeAre you the author of 1500 Request Building 4209185a?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tools-only-1500-request-building-4209185a)# 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
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.