NSURLRequest
HTTP Header
iOS Development
Swift Programming
Networking

NSURLRequest setting the HTTP header

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Setting HTTP headers is a normal part of networking on Apple platforms. You use headers to describe the body you are sending, request a response format, attach authentication, and control caching behavior. The part that trips people up is that NSURLRequest itself is immutable, so you need a mutable request type when you want to set or change headers.

In modern Swift that usually means URLRequest. In Objective-C it is commonly NSMutableURLRequest. The underlying idea is the same: create a mutable request, set headers, then send it with URLSession.

Use A Mutable Request

In Objective-C, the direct pattern looks like this:

objective-c
1NSURL *url = [NSURL URLWithString:@"https://api.example.com/items"];
2NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
3
4[request setHTTPMethod:@"POST"];
5[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
6[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
7[request setValue:@"Bearer TOKEN123" forHTTPHeaderField:@"Authorization"];

That is the standard answer: use setValue:forHTTPHeaderField: on a mutable request.

In Swift, the same request is usually written with URLRequest:

swift
1import Foundation
2
3var request = URLRequest(url: URL(string: "https://api.example.com/items")!)
4request.httpMethod = "POST"
5request.setValue("application/json", forHTTPHeaderField: "Content-Type")
6request.setValue("application/json", forHTTPHeaderField: "Accept")
7request.setValue("Bearer TOKEN123", forHTTPHeaderField: "Authorization")

setValue Versus addValue

Apple provides two similar methods:

  • 'setValue(_:forHTTPHeaderField:)'
  • 'addValue(_:forHTTPHeaderField:)'

The difference matters:

  • 'setValue replaces any existing value for that header field'
  • 'addValue appends another value'

Use setValue for most cases. It is the safer default for Authorization, Content-Type, and Accept.

swift
request.setValue("application/json", forHTTPHeaderField: "Accept")

Use addValue only when multiple values are intentional:

swift
request.addValue("gzip", forHTTPHeaderField: "Accept-Encoding")

If you accidentally call addValue repeatedly for a header that should be singular, you can end up sending duplicates that are hard to notice during debugging.

Keep Headers Consistent With The Body

The most common header mistake is setting fields that do not match the body you send. If you post JSON, encode JSON and declare that fact clearly:

swift
1import Foundation
2
3let payload: [String: Any] = [
4    "name": "Widget",
5    "quantity": 3
6]
7
8var request = URLRequest(url: URL(string: "https://api.example.com/items")!)
9request.httpMethod = "POST"
10request.setValue("application/json", forHTTPHeaderField: "Content-Type")
11request.setValue("application/json", forHTTPHeaderField: "Accept")
12request.httpBody = try JSONSerialization.data(withJSONObject: payload)

If the server expects JSON and the header says something else, the request may still reach the server but be rejected or parsed incorrectly.

Reuse Shared Headers In One Place

If every API call in your app needs the same headers, centralize that logic. Do not rebuild authorization and content rules in every screen or service class.

swift
1func makeAuthorizedRequest(path: String, token: String) -> URLRequest {
2    var request = URLRequest(url: URL(string: "https://api.example.com\(path)")!)
3    request.setValue("application/json", forHTTPHeaderField: "Accept")
4    request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
5    return request
6}

That keeps the networking layer predictable and makes auth bugs much easier to debug. It also reduces the chance that one request forgets a required header while another includes it.

Header Names And Semantics

HTTP header names are case-insensitive, so capitalization is mostly a readability issue. The bigger problem is using the wrong header for the job. Content-Type describes the body you send, Accept describes the kind of response you want back, and Authorization carries credentials or tokens. Mixing those up produces more real bugs than letter case ever will.

Common Pitfalls

  • Trying to modify an immutable NSURLRequest instead of using NSMutableURLRequest or Swift URLRequest.
  • Using addValue when you really want to replace a header with setValue.
  • Setting Content-Type without encoding the body in the matching format.
  • Confusing Accept with Content-Type.
  • Duplicating header-building logic throughout the app instead of centralizing it.

Summary

  • Set headers on a mutable request type, not on immutable NSURLRequest.
  • Use setValue:forHTTPHeaderField: for most headers.
  • Use addValue:forHTTPHeaderField: only when multiple values are intentional.
  • Keep request headers consistent with the actual body format.
  • Centralize shared headers so authorization and content rules stay consistent.

Course illustration
Course illustration

All Rights Reserved.