 			registerBodyDeserializer(deserializer, forContentType: contentType)
 		}
 	}
+
+	/// Finds a body deserializer by pattern.
+	///
+	/// - Parameter contentType: The content type to find a deserializer for.
+	///
+	/// - Returns: A body deserializer for given `contentType` or `nil`.
+	private static func findBodyDeserializerForContentType(contentType: String) -> BodyDeserializer? {
+		for (pattern, deserializer) in defaultBodyDeserializers.appendingElementsOf(dictionary: customBodyDeserializers) {
+			let patternParts = pattern.componentsSeparatedByString("/")
+			let actualParts = contentType.componentsSeparatedByString("/")
+			guard patternParts.count == 2 && actualParts.count == 2 else {
+				return nil
+			}
+			if ["*" , actualParts[0]].contains(patternParts[0]) && ["*" , actualParts[1]].contains(patternParts[1]) {
+				return deserializer
+			}
+		}
+		return nil
+	}
 	
 	/// Deserializes a HTTP body into a string.
 	///


import Foundation

@objc(RDTResponseDetective) public final class ResponseDetective: NSObject {
	
	/// Whether ResponseDetective is enabled.
	public static var enabled: Bool = false {
		didSet {
			if enabled {
				NSURLProtocol.registerClass(URLProtocolClass)
			} else {
				NSURLProtocol.unregisterClass(URLProtocolClass)
			}
		}
	}
	
	/// An output facility for reporting requests, responses and errors.
	public static var outputFacility: OutputFacility = ConsoleOutputFacility()
	
	/// A class of the URL protocol used to intercept requests.
	public static let URLProtocolClass: AnyClass = URLProtocol.self
	
	/// A storage for request predicates.
	private static var requestPredicates: [NSPredicate] = []
	
	/// Body deserializers stored by a supported content type.
	private static var bodyDeserializers: [String: BodyDeserializer] = [
		"*/json": JSONBodyDeserializer(),
		"*/xml": XMLBodyDeserializer(),
		"*/html": HTMLBodyDeserializer(),
		"image/*": ImageBodyDeserializer(),
		"text/plain": PlaintextBodyDeserializer(),
	]
	
	/// Resets the ResponseDetective mutable state.
	public static func reset() {
		enabled = false
		outputFacility = ConsoleOutputFacility()
		requestPredicates = []
	}
	
	/// Ignores requests matching the given predicate. The predicate will be
	/// evaluated with an instance of NSURLRequest.
	///
	/// - Parameter predicate: A predicate for matching a request. If the
	/// predicate evaluates to `false`, the request is not intercepted.
	public static func ignoreRequestsMatchingPredicate(predicate: NSPredicate) {
		requestPredicates.append(predicate)
	}

	///     - contentType: The content type of the body.
	///
	/// - Returns: A deserialized body or `nil` if no serializer is capable of
	///   deserializing body with the given content type.
	public static func deserializeBody(body: NSData, contentType: String) -> String? {
		if let deserializer = findBodyDeserializerForContentType(contentType) {
			return deserializer.deserializeBody(body)
		} else {
			return nil
