       }
     }
   }
+  
+  private func verifyResponse(response: NSHTTPURLResponse, forAsset asset: Asset) throws {
+    // A response with a non-success status code should not be considered a succesful download
+    if !(200..<300).contains(response.statusCode) {
+      throw WebAppError.DownloadFailure(reason: "Non-success status code for asset: \(asset)", underlyingError: nil)
+      // If we have a hash for the asset, and the ETag header also specifies
+      // a hash, we compare these to verify if we received the expected asset version
+    } else if let expectedHash = asset.hash,
+      let ETag = response.allHeaderFields["ETag"] as? String,
+      let actualHash = SHA1HashFromETag(ETag)
+      where actualHash != expectedHash {
+        throw WebAppError.DownloadFailure(reason: "Hash mismatch for asset: \(asset)", underlyingError: nil)
+    }
+  }
 }

  }
  
  func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
  }

  func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {

  }
  
  private func cancelAndFailWithReason(reason: String, underlyingError: ErrorType? = nil) {
    let error = WebAppError.DownloadFailure(reason: reason, underlyingError: underlyingError)
    cancelAndFailWithError(error)
  }
  
  private func cancelAndFailWithError(error: ErrorType) {
    cancel()
    
    delegate?.assetBundleDownloader(self, didFailWithError: error)
  }
  
