<commit_before>//
//  AlamoFireNetwork.swift
//  pgoapi
//
//  Created by <NAME> on 2016/07/27.
//  Copyright © 2016 MC. All rights reserved.
//

import Foundation
import Alamofire
import BoltsSwift

open class AlamoFireNetwork: Network, Synchronizable
{
    private let defaultManager: SessionManager
    private var isolatedManagerMap: [String: SessionManager] = [:] // maps sessionID to manager
    private let callbackQueue = DispatchQueue(label: "AlamoFire Network Callback Queue", attributes: DispatchQueue.Attributes.concurrent)
    
    let synchronizationLock: DispatchQueue = DispatchQueue(label: "AlamoFireNetwork Synchronization", attributes: [])
    
    open var processingExecutor: Executor = {
        let queue = OperationQueue()
        queue.name = "AlamoFire Network Process Queue"
        return Executor.operationQueue(queue)
    }()
    
    open class func defaultFireNetwork() -> AlamoFireNetwork
    {
        let configuration = URLSessionConfiguration.default
        var headers = SessionManager.defaultHTTPHeaders
        
        headers["User-Agent"] = getUserAgent()
        configuration.httpAdditionalHeaders = headers
        
        let manager = SessionManager(configuration: configuration)
        manager.delegate.taskWillPerformHTTPRedirection = { session, task, response, request in return nil }
        return AlamoFireNetwork(manager: manager)
    }
    
    public init(manager: SessionManager)
    {
        self.defaultManager = manager
    }
    
    open func resetSessionWithID(sessionID: String)
    {
        sync{ self.isolatedManagerMap.removeValue(forKey: sessionID) }
    }
    
    open func getJSON(_ endPoint: String, args: RequestArgs?) -> Task<NetworkResponse<Any>>
    {
        let responseMethod = ResponseMethod { (request, queue, handler) in request.responseJSON(queue: queue, completionHandler: handler) }
        return self.request(.get, endPoint: endPoint, args: args, responseMethod: responseMethod)
    }
    
    open func postData(_ endPoint: String,  args: RequestArgs?) -> Task<NetworkResponse<Data>>
    {
        let responseMethod = ResponseMethod { (request, queue, handler) in request.responseData(queue: queue, completionHandler: handler) }
        return self.request(.post, endPoint: endPoint, args: args, responseMethod: responseMethod)
    }
    
    open func postString(_ endPoint: String,  args: RequestArgs?) -> Task<NetworkResponse<String>>
    {
        let responseMethod = ResponseMethod { (request, queue, handler) in request.responseString(queue: queue, completionHandler: handler) }
        return self.request(.post, endPoint: endPoint, args: args, responseMethod: responseMethod)
    }
    
    private func request<T>(_ method: HTTPMethod,
                            endPoint: String,
                            args: RequestArgs?,
                            responseMethod: ResponseMethod<T>) -> Task<NetworkResponse<T>>
    {
        let manager = managerFor(args)
        
        let taskSource = TaskCompletionSource<NetworkResponse<T>>()
        let encoding = encodingFor(args: args)
        
        let request = manager.request(endPoint, method: method, parameters: args?.params, encoding: encoding)
        responseMethod.invocation(request, callbackQueue)
        {
            (response: DataResponse<T>) in
            
            switch response.result
            {
            case .success(let value):
                taskSource.set(result: NetworkResponse(url: response.response?.url,
                                                       statusCode: response.response?.statusCode ?? 0,
                                                       response: value,
                                                       responseHeaders: response.response?.allHeaderFields as? [String: String]))
            case .failure(let error):
                taskSource.set(error: error)
            }
        }
        
        return taskSource.task
    }
    
    private func encodingFor(args: RequestArgs?) -> ParameterEncoding
    {
        if let body = args?.body
        {
            return DataBodyParameterEncoding(body: body)
        }
        return URLEncoding(destination: .methodDependent)<commit_msg>Fix an issue with the AlamoFireNetwork implementation preventing request headers from being sent<commit_after>//
//  AlamoFireNetwork.swift
//  pgoapi
//
//  Created by <NAME> on 2016/07/27.
//  Copyright © 2016 MC. All rights reserved.
//

import Foundation
import Alamofire
import BoltsSwift

open class AlamoFireNetwork: Network, Synchronizable
{
    private let defaultManager: SessionManager
    private var isolatedManagerMap: [String: SessionManager] = [:] // maps sessionID to manager
    private let callbackQueue = DispatchQueue(label: "AlamoFire Network Callback Queue", attributes: DispatchQueue.Attributes.concurrent)
    
    let synchronizationLock: DispatchQueue = DispatchQueue(label: "AlamoFireNetwork Synchronization", attributes: [])
    
    open var processingExecutor: Executor = {
        let queue = OperationQueue()
        queue.name = "AlamoFire Network Process Queue"
        return Executor.operationQueue(queue)
    }()
    
    open class func defaultFireNetwork() -> AlamoFireNetwork
    {
        let configuration = URLSessionConfiguration.default
        var headers = SessionManager.defaultHTTPHeaders
        
        headers["User-Agent"] = getUserAgent()
        configuration.httpAdditionalHeaders = headers
        
        let manager = SessionManager(configuration: configuration)
        manager.delegate.taskWillPerformHTTPRedirection = { session, task, response, request in return nil }
        return AlamoFireNetwork(manager: manager)
    }
    
    public init(manager: SessionManager)
    {
        self.defaultManager = manager
    }
    
    open func resetSessionWithID(sessionID: String)
    {
        sync{ self.isolatedManagerMap.removeValue(forKey: sessionID) }
    }
    
    open func getJSON(_ endPoint: String, args: RequestArgs?) -> Task<NetworkResponse<Any>>
    {
        let responseMethod = ResponseMethod { (request, queue, handler) in request.responseJSON(queue: queue, completionHandler: handler) }
        return self.request(.get, endPoint: endPoint, args: args, responseMethod: responseMethod)
    }
    
    open func postData(_ endPoint: String,  args: RequestArgs?) -> Task<NetworkResponse<Data>>
    {
        let responseMethod = ResponseMethod { (request, queue, handler) in request.responseData(queue: queue, completionHandler: handler) }
        return self.request(.post, endPoint: endPoint, args: args, responseMethod: responseMethod)
    }
    
    open func postString(_ endPoint: String,  args: RequestArgs?) -> Task<NetworkResponse<String>>
    {
        let responseMethod = ResponseMethod { (request, queue, handler) in request.responseString(queue: queue, completionHandler: handler) }
        return self.request(.post, endPoint: endPoint, args: args, responseMethod: responseMethod)
    }
    
    private func request<T>(_ method: HTTPMethod,
                            endPoint: String,
                            args: RequestArgs?,
                            responseMethod: ResponseMethod<T>) -> Task<NetworkResponse<T>>
    {
        let manager = managerFor(args)
        
        let taskSource = TaskCompletionSource<NetworkResponse<T>>()
        let encoding = encodingFor(args: args)
        
        let request = manager.request(endPoint, method: method, parameters: args?.params, encoding: encoding, headers: args?.headers)
        responseMethod.invocation(request, callbackQueue)
        {
            (response: DataResponse<T>) in
            
            switch response.result
            {
            case .success(let value):
                taskSource.set(result: NetworkResponse(url: response.response?.url,
                                                       statusCode: response.response?.statusCode ?? 0,
                                                       response: value,
                                                       responseHeaders: response.response?.allHeaderFields as? [String: String]))
            case .failure(let error):
                taskSource.set(error: error)
            }
        }
        
        return taskSource.task
    }
    
    private func encodingFor(args: RequestArgs?) -> ParameterEncoding
    {
        if let body = args?.body
        {
            return DataBodyParameterEncoding(body: body)
        }
        return URLEncoding(destination: .methodDependent)
{'fraction_non_alphanumeric': 0.08550402990304871, 'fraction_numerical': 0.003037028384534517, 'mean_word_length': 2.4248, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5829066', 'n_tokens_mistral': 2108, 'n_tokens_neox': 2060, 'n_words': 551}