0001    // ContentNegotiatonMiddleware.swift
0002    //
0003    // The MIT License (MIT)
0004    //
0005    // Copyright (c) 2015 Zewo
0006    //
0007    // Permission is hereby granted, free of charge, to any person obtaining a copy
0008    // of this software and associated documentation files (the "Software"), to deal
0009    // in the Software without restriction, including without limitation the rights
0010    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0011    // copies of the Software, and to permit persons to whom the Software is
0012    // furnished to do so, subject to the following conditions:
0013    //
0014    // The above copyright notice and this permission notice shall be included in all
0015    // copies or substantial portions of the Software.
0016    //
0017    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0018    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0019    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0020    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0021    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0022    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0023    // SOFTWARE.
0024    
0025    @_exported import HTTP
0026    @_exported import MediaTypeParserCollection
0027    @_exported import MediaTypeSerializerCollection
0028    
0029    public final class ServerContentNegotiationMiddleware: MiddlewareType {
0030        public let parsers: MediaTypeParserCollection
0031        public let serializers: MediaTypeSerializerCollection
0032    
0033        public init(parsers: MediaTypeParserCollection, serializers: MediaTypeSerializerCollection) {
0034            self.parsers = parsers
0035            self.serializers = serializers
0036        }
0037    
0038        public func respond(request: Request, chain: ChainType) throws -> Response {
0039            var request = request
0040    
0041            guard case .Buffer(let body) = request.body else {
0042                return try chain.proceed(request)
0043            }
0044    
0045            if let contentType = request.contentType {
0046                do {
0047                    let (_, content) = try parsers.parse(body, mediaType: contentType)
0048                    request.content = content
0049                } catch MediaTypeParserCollectionError.NoSuitableParser {
0050                    return Response(status: .UnsupportedMediaType)
0051                } catch {
0052                    return Response(status: .BadRequest)
0053                }
0054            }
0055    
0056            var response = try chain.proceed(request)
0057    
0058            if let content = response.content {
0059                do {
0060                    let mediaTypes = request.accept.count > 0 ? request.accept : serializers.mediaTypes
0061                    let (mediaType, body) = try serializers.serialize(content, mediaTypes: mediaTypes)
0062                    response.contentType = mediaType
0063                    response.body = .Buffer(body)
0064                    response.contentLength = body.count
0065                } catch MediaTypeSerializerCollectionError.NoSuitableSerializer {
0066                    return Response(status: .NotAcceptable)
0067                } catch {
0068                    return Response(status: .InternalServerError)
0069                }
0070            }
0071    
0072            return response
0073        }
0074    }
0075    
0076    public final class ClientContentNegotiatonMiddleware: MiddlewareType {
0077        public let parsers: MediaTypeParserCollection
0078        public let serializers: MediaTypeSerializerCollection
0079        public let mediaTypes: [MediaType]
0080    
0081        public init(parsers: MediaTypeParserCollection, serializers: MediaTypeSerializerCollection, mediaTypes: MediaType...) {
0082            self.parsers = parsers
0083            self.serializers = serializers
0084            self.mediaTypes = mediaTypes
0085        }
0086    
0087        public func respond(request: Request, chain: ChainType) throws -> Response {
0088            var request = request
0089    
0090            request.accept = parsers.mediaTypes
0091    
0092            if let content = request.content {
0093                let (mediaType, body) = try serializers.serialize(content, mediaTypes: mediaTypes)
0094                request.contentType = mediaType
0095                request.body = .Buffer(body)
0096                request.contentLength = body.count
0097            }
0098    
0099            var response = try chain.proceed(request)
0100    
0101            guard case .Buffer(let body) = response.body else {
0102                return response
0103            }
0104    
0105            if let contentType = response.contentType {
0106                let (_, content) = try parsers.parse(body, mediaType: contentType)
0107                response.content = content
0108            }
0109    
0110            return response
0111        }
0112    }
0113    
0114    extension Request {
0115        public var content
ContentNegotiatonMiddleware.swift:139
    public var content: InterchangeData? {
: InterchangeData? { 0116 set { 0117 storage["content"] = newValue 0118 } 0119 0120 get { 0121 return storage["content"] as? InterchangeData ?? nil 0122 } 0123 } 0124 0125 public init(method: Method, uri: URI, headers: Headers = [:], content: InterchangeData, upgrade: Upgrade? = nil) { 0126 self.init( 0127 method: method, 0128 uri: uri, 0129 headers: headers, 0130 body: nil, 0131 upgrade: upgrade 0132 ) 0133 0134 self.content = content 0135 } 0136 } 0137 0138 extension Response { 0139 public var content: InterchangeData? { 0140 set { 0141 storage["content"] = newValue 0142 } 0143 0144 get { 0145 return storage["content"] as? InterchangeData ?? nil 0146 } 0147 } 0148 0149 public init
ContentNegotiatonMiddleware.swift:125
    public init(method: Method, uri: URI, headers: Headers = [:], content: InterchangeData, upgrade: Upgrade? = nil) {
(status: Status = .OK, headers: Headers = [:], content: InterchangeData, upgrade: Upgrade? = nil) { 0150 self.init( 0151 status: status, 0152 headers: headers, 0153 body: nil, 0154 upgrade: upgrade 0155 ) 0156 0157 self.content = content 0158 } 0159 }