Files
2019-01-27 11:57:06 -05:00

99 lines
3.7 KiB
Swift
Executable File

//
// ResponseMiddleware.swift
//
// Copyright © 2017 Peter Zignego. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
public struct ResponseMiddleware: Middleware {
let token: String
let response: SKResponse
public init(token: String, response: SKResponse) {
self.token = token
self.response = response
}
public func respond(to request: (RequestType, ResponseType)) -> (RequestType, ResponseType) {
if let respondable = Respondable(request: request.0), respondable.token == token {
return (request.0, Response(response: response))
}
return (request.0, Response(400))
}
private struct Respondable {
let token: String
init?(request: RequestType) {
if let webhook = WebhookRequest(request: request), let token = webhook.token {
self.token = token
} else if let action = MessageActionRequest(request: request), let token = action.token {
self.token = token
} else {
return nil
}
}
}
}
extension WebhookRequest {
public init?(request: RequestType) {
guard
let proto = request.headers.first(where: {$0.name.lowercased() == "x-forwarded-proto"})?.value,
let host = request.headers.first(where: {$0.name.lowercased() == "host"})?.value
else {
return nil
}
let requestString = proto + host + request.path + "?" + request.body!
let components = URLComponents(string: requestString)
var dict = [String: Any]()
_ = components?.queryItems.flatMap {$0.map({dict[$0.name]=$0.value})}
self.init(request: dict)
}
}
extension MessageActionRequest {
public init?(request: RequestType) {
guard
let response = request.formURLEncodedBody.first(where: {$0.name.lowercased() == "payload" })?.value,
let data = response.data(using: .utf8),
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any]
else {
return nil
}
self.init(response: json)
}
}
extension Response {
public init(response: SKResponse) {
if response.attachments == nil {
try! self.init(200, response.text)
} else if
let data = try? JSONSerialization.data(withJSONObject: response.json, options: []),
let body = String(data: data, encoding: .utf8) {
try! self.init(code: 200, body: body, headers: HTTPHeaders(headers: [Header(name: "content-type", value: "application/json")]))
} else {
self.init(400)
}
}
}