| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- //
- // HttpRequest.swift
- // Swifter
- // Copyright (c) 2015 Damian Kołakowski. All rights reserved.
- //
- import Foundation
- public class HttpRequest {
-
- public var path: String = ""
- public var queryParams: [(String, String)] = []
- public var method: String = ""
- public var headers: [String: String] = [:]
- public var body: [UInt8] = []
- public var address: String? = ""
- public var params: [String: String] = [:]
-
- public func parseUrlencodedForm() -> [(String, String)] {
- guard let contentTypeHeader = headers["content-type"] else {
- return []
- }
- let contentTypeHeaderTokens = contentTypeHeader.split(";").map { $0.trim() }
- guard let contentType = contentTypeHeaderTokens.first where contentType == "application/x-www-form-urlencoded" else {
- return []
- }
- return String.fromUInt8(body).split("&").map { (param: String) -> (String, String) in
- let tokens = param.split("=")
- if let name = tokens.first, value = tokens.last where tokens.count == 2 {
- return (name.replace("+", new: " ").removePercentEncoding(),
- value.replace("+", new: " ").removePercentEncoding())
- }
- return ("","")
- }
- }
-
- public struct MultiPart {
- public let headers: [String: String]
- public let body: [UInt8]
- }
-
- public func parseMultiPartFormData() -> [MultiPart] {
- guard let contentTypeHeader = headers["content-type"] else {
- return []
- }
- let contentTypeHeaderTokens = contentTypeHeader.split(";").map { $0.trim() }
- guard let contentType = contentTypeHeaderTokens.first where contentType == "multipart/form-data" else {
- return []
- }
- var boundary: String? = nil
- contentTypeHeaderTokens.forEach({
- let tokens = $0.split("=")
- if let key = tokens.first where key == "boundary" && tokens.count == 2 {
- boundary = tokens.last
- }
- })
- if let boundary = boundary where boundary.utf8.count > 0 {
- return parseMultiPartFormData(body, boundary: "--\(boundary)")
- }
- return []
- }
-
- private func parseMultiPartFormData(data: [UInt8], boundary: String) -> [MultiPart] {
- var generator = data.generate()
- var result = [MultiPart]()
- while let part = nextMultiPart(&generator, boundary: boundary, isFirst: result.isEmpty) {
- result.append(part)
- }
- return result
- }
-
- private func nextMultiPart(inout generator: IndexingGenerator<[UInt8]>, boundary: String, isFirst: Bool) -> MultiPart? {
- if isFirst {
- guard nextMultiPartLine(&generator) == boundary else {
- return nil
- }
- } else {
- nextMultiPartLine(&generator)
- }
- var headers = [String: String]()
- while let line = nextMultiPartLine(&generator) where !line.isEmpty {
- let tokens = line.split(":")
- if let name = tokens.first, value = tokens.last where tokens.count == 2 {
- headers[name.lowercaseString] = value.trim()
- }
- }
- guard let body = nextMultiPartBody(&generator, boundary: boundary) else {
- return nil
- }
- return MultiPart(headers: headers, body: body)
- }
-
- private func nextMultiPartLine(inout generator: IndexingGenerator<[UInt8]>) -> String? {
- var result = String()
- while let value = generator.next() {
- if value > HttpRequest.CR {
- result.append(Character(UnicodeScalar(value)))
- }
- if value == HttpRequest.NL {
- break
- }
- }
- return result
- }
-
- static let CR = UInt8(13)
- static let NL = UInt8(10)
-
- private func nextMultiPartBody(inout generator: IndexingGenerator<[UInt8]>, boundary: String) -> [UInt8]? {
- var body = [UInt8]()
- let boundaryArray = [UInt8](boundary.utf8)
- var matchOffset = 0;
- while let x = generator.next() {
- matchOffset = ( x == boundaryArray[matchOffset] ? matchOffset + 1 : 0 )
- body.append(x)
- if matchOffset == boundaryArray.count {
- body.removeRange(Range<Int>(start: body.count-matchOffset, end: body.count))
- if body.last == HttpRequest.NL {
- body.removeLast()
- if body.last == HttpRequest.CR {
- body.removeLast()
- }
- }
- return body
- }
- }
- return nil
- }
- }
|