         { }
     }
 
-class RequestStub
+struct RequestMatcher
     {
     var method: String
     var url: String
-
-    init(method: String, url: String, status: Int = 200)
-        {
-        self.method = method
-        self.url = url
+    var headers = [String:String]()
+    var body: Data?
+
+    func matches(_ request: URLRequest) -> Bool
+        {
+        return request.httpMethod == method
+            && request.url?.absoluteString == url
+            && headers.allSatisfy
+                {
+                key, value in
+                request.allHTTPHeaderFields?[key] == value
+                }
+        }
+    }
+
+class RequestStub
+    {
+    var matcher: RequestMatcher
+
+    init(matcher: RequestMatcher, status: Int = 200)
+        {
+        self.matcher = matcher
         self.responseCode = status
         }
-
-    var requestHeaders = [String:String]()
-    var requestBody: Data?
 
     var responseError: Error?
     var responseCode: Int


    func withBody(_ data: Data) -> Self
        {
        stub.requestBody = data
        return self
        }



    let delayLatch = Latch(name: "delayed request")

    var description: String
        { "\(matcher) → \(responseCode)" }
    }

@discardableResult
func stubRequest(_ resource: () -> Resource, _ method: String) -> LSStubRequestDSL
    {
    let stub = RequestStub(matcher: RequestMatcher(method: method, url: resource().url.absoluteString))
    NetworkStub.add(stub)
    return LSStubRequestDSL(stub: stub)
    }
