don't stop believing

[macaron 1] macaron api 시작하기 본문

Swift/Perfect

[macaron 1] macaron api 시작하기

Tongchun 2017. 12. 31. 21:37

사내 인트라넷으로 사용할 macaron의 api 서버를 swift perfect로 만들어 보겠습니다.

인트라넷의 구조는 swift perfect로 api 서버를 만들고 web 서버로 php, 앱은 네이티브로 만들 계획입니다.

macaron api의 개발 가정을 기록해 보겠습니다.


swift 버전부터 확인하겠습니다. 버전은 4.0.3입니다.

$ swift -version
Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2)
Target: x86_64-apple-macosx10.9

프로젝트 폴더로 이동해 swift package init으로 초기화 하겠습니다.

$ cd ~/Documents/macaron-api
$ swift package init --type executable

기본 구성의 시작은 Perfect 서버 기본 알이보기와 Perfect 구조 잡기를 기본으로 구성하겠습니다.

[Perfect 서버 기본 알이보기]

[Perfect 구조 잡기]

Perfect 구조 잡기에서 처럼 시작은 main.swift와 controller.swift로 나누겠습니다. main.swift 파일이 있는 위치에 controller.swift를 추가해 줍니다.

$ cd Sources/macaron-api/
$ touch controller.swift

이제 xcode project를 만들어 기본 코딩을 합니다.

$ swift package generate-xcodeproj
$ open macaron-api.xcodeproj/

Package.swift 파일을 열고 아래와 같이 코딩합니다.

// swift-tools-version:3.1.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "macaron-api",
    targets: [
        Target(
            name: "macaron-api",
            dependencies: []),
        ],
    dependencies: [
        .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 3),
        .Package(url: "https://github.com/PerfectlySoft/Perfect-Mustache.git", majorVersion: 3),
        .Package(url: "https://github.com/SwiftORM/StORM.git", majorVersion: 3),
    ]
)

swift 4에서는 SPM에서 swift-tools-version을 지정할 수 있습니다. perfect는 3.1.0을 지원하기 때문에 버전을 지정합니다.

[swift4와 perfect]

main.swift 파일을 열고 아래와 같이 코딩합니다.

api 포트는 1026으로 합니다. webroot 폴더는 아직 안만들었네요.

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import PerfectMustache

let server = HTTPServer()
server.serverPort = 1026
server.documentRoot = "webroot"

let controller = Controller()
server.addRoutes(Routes(controller.routes))

do {
    try server.start()
} catch PerfectError.networkError(let err, let msg) {
    print("Network error thrown: \(err) \(msg)")
}

그 다음은 controller.swift 입니다.

import Foundation
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer

final class Controller {
    var routes: [Route] {
        return [
            Route(method: .get, uri: "/", handler: sayHellobyString),
            Route(method: .get, uri: "/json", handler: sayHellobyJson),
            Route(method: .get, uri: "/json/second", handler: scondPathJson),
            Route(method: .get, uri: "/json/{name}/{age}", handler: urlVariables),
            Route(method: .post, uri: "/post", handler: postParam)
        ]
    }
    
    func returnJSONMessage(message: String, response: HTTPResponse) {
        do {
            try response.setBody(json: ["message": message])
                .setHeader(.contentType, value: "application/json")
                .completed()
        } catch {
            response.setBody(string: "Error handling request: \(error)")
                .completed(status: .internalServerError)
        }
    }
    
    func sayHellobyString(request: HTTPRequest, response: HTTPResponse) {
        do {
            response.setBody(string: "hello tongchun, you are at root directory with get.")
                .completed()
        } catch {
            response.setBody(string: "Error handling request: \(error)")
                .completed(status: .internalServerError)
        }
    }
    
    func sayHellobyJson(request: HTTPRequest, response: HTTPResponse) {
        do {
            returnJSONMessage(message: "hello tongchun, you are at json directory with get.", response: response)
        } catch {
            response.setBody(string: "Error handling request: \(error)")
                .completed(status: .internalServerError)
        }
    }
    
    func scondPathJson(request: HTTPRequest, response: HTTPResponse) {
        do {
            returnJSONMessage(message: "you are at /json/second with get.", response: response)
        } catch {
            response.setBody(string: "Error handling request: \(error)")
                .completed(status: .internalServerError)
        }
    }
    
    func urlVariables(request: HTTPRequest, response: HTTPResponse) {
        do {
            guard let userName = request.urlVariables["name"], let userAge = request.urlVariables["age"] else {
                response.completed(status: .badRequest)
                return
            }
            returnJSONMessage(message: "Your name is \(userName) and age is \(userAge)", response: response)
        } catch {
            response.setBody(string: "Error handling request: \(error)")
                .completed(status: .internalServerError)
        }
    }
    
    func postParam(request: HTTPRequest, response: HTTPResponse) {
        do {
            guard let name = request.param(name: "name"), let age = request.param(name: "age") else {
                response.completed(status: .badRequest)
                return
            }
            returnJSONMessage(message: "You sent me by post and data is \(name) / \(age)", response: response)
        } catch {
            response.setBody(string: "Error handling request: \(error)")
                .completed(status: .internalServerError)
        }
    }
    
    func postJson(request: HTTPRequest, response: HTTPResponse) {
        guard let jsonString = request.postBodyString else {
            response.completed(status: .badRequest)
            return
        }

        do {
            let jsonDic = try jsonString.jsonDecode() as! [String: String]
            let userName = jsonDic["name"]!
            let userAge = jsonDic["age"]!
            
            returnJSONMessage(message: "Your name is \(userName) and your age is \(userAge)", response: response)
        } catch {
            response.completed(status: .internalServerError)
            return
        }
    }
}

이제 여기서 부터 개발을 시작하겠습니다.



Comments