Creating cURL command from URLRequest in LLDB


I have recently looked into how you can add custom LLDB commands that you can use for debugging in Xcode. The process is quite simple and it’s very useful to have custom commands that are used repeatedly.


Creating a custom LLDB command

I found that the easiest way to do that is to use command regex LLDB command. You can find more info about it by opening terminal and typing lldb and then help command regex.

Something that I needed often when debugging networking code is a full cURL command that I can then test in my terminal or send it to a backend engineer for further inspection. That’s why I created an LLDB command that outputs a cURL command from a URLRequest instance.

The process for creating such a command looks like this:

func curl(from urlRequest: URLRequest) {
  guard let url = urlRequest.url else { return }
  var baseCommand = #"curl "\#(url.absoluteString)""#
  if urlRequest.httpMethod == "HEAD" {
    baseCommand += " --head"
  }
  
  var command = [baseCommand]
  if let method = urlRequest.httpMethod, method != "GET" && method != "HEAD" {
    command.append("-X \(method)")
  }
  
  if let headers = urlRequest.allHTTPHeaderFields {
    for (key, value) in headers where key != "Cookie" {
      command.append("-H '\(key): \(value)'")
    }
  }
  
  if let data = urlRequest.httpBody, let body = String(data: data, encoding: .utf8) {
    command.append("-d '\(body)'")
  }
  
  print(command.joined(separator: " \\\n\t"))
}
command regex curl 's|(.+)|expr let inputRequest = %1; guard let url = inputRequest.url else { print("");return };var baseCommand = #"curl "\#(url.absoluteString)""#;if inputRequest.httpMethod == "HEAD" { baseCommand += " --head" };var command = [baseCommand];if let method = inputRequest.httpMethod, method != "GET" && method != "HEAD" { command.append("-X \(method)") };if let headers = inputRequest.allHTTPHeaderFields { for (key, value) in headers where key != "Cookie" { command.append("-H '\''\(key): \(value)'\''") } };if let data = inputRequest.httpBody, let body = String(data: data, encoding: .utf8) { command.append("-d ''\(body)''") };print(command.joined(separator: " \\\n\t"))|

NOTE: You need to escape the single quote characters to avoid errors when the command is initialized. You can do that by replacing ' with '\''.

Now, each time you are debugging a project you can use the custom command like this:

(lldb) curl request

curl "https://mywebsite.com" \
	-H 'Accept: application/json' \
	-H 'Authorization: Basic htu574kfj584kfnd84kdlwut92jayebgpylg8md72msgrk'

In the end, I recommend watching this great talk on advanced debugging by Dave Lee.