don't stop believing

Perfect로 redis에 연결해 봅시다. 1 본문

Swift/Perfect

Perfect로 redis에 연결해 봅시다. 1

Tongchun 2018. 1. 17. 17:56

Perfect의 Perfect-Session-Redis-Demo를 참고하여 Redis와 Session 사용에 대해 확인해 보겠습니다.

https://github.com/PerfectExamples/Perfect-Session-Redis-Demo


Perfect Redis: https://github.com/PerfectlySoft/Perfect-Redis

Perfect Session: https://perfect.org/docs/sessions.html


Remind 차원에서 처음부터 차근차근 시작해 보겠습니다.

먼저 swift 버전을 확인해 봅시다.

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

개발 환경은 Mac OS입니다.

Terminal에서 프로젝트 폴더를 만들고 swift package를 초기화 해줍니다.

$ mkdir nGleServer005
$ cd nGleServer005
$ swift package init --type executable

Package.swift 파일과 몇 개의 폴더가 생성됩니다.

바로 xCode project로 변환해 xcode로 프로젝트를 열어 줍니다.

$ swift package generate-xcodeproj
$ open nGleServer005.xcodeproj

xCode에서 Package.swift파일을 열고 dependencies에 Perfect-HTTPServerPerfect-Session-Redis를 추가합니다.

// swift-tools-version:4.0

import PackageDescription

let package = Package(
    name: "nGleServer005",
    dependencies: [
        .package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", from: "3.0.0"),
        .package(url: "https://github.com/PerfectlySoft/Perfect-Session-Redis.git", from: "3.0.0"),
    ],
    targets: [
        .target(
            name: "nGleServer005",
            dependencies: ["PerfectHTTPServer", "PerfectSessionRedis"]),
    ]
)

swift 3.0일때와 크게 달라진 부분은 dependencies에 추가 후 targets의 dependencies에도 import되는 package를 추가해야 합니다. 그렇지 않으면 xcodeproj 변환 후 xCode에서 해당 package들이 등록되지 않습니다.

xcode에서 Package.swift파일을 저장하고 terminal에서 package update를 해줍니다.

$ swift package update

실행하면 github에 있는 package들이 clone되는 것을 확인할 수 있습니다.

swift 빌드도 해봅시다.

$ swift build

빌드가 정상적으로 되었다면 다시 xcodeproj로 변환하고 열어 줍니다.

$ swift package generate-xcodeproj
$ open nGleServer005.xcodeproj

xCode의 오른쪽 Target Membership창에 dependencies에 추가된 package들을 확인할 수 있습니다.

이제 파일을 추가합니다. main.swift가 있는 위치에 Routes.swift와 Handlers.swift 파일을 추가합니다.

Routes.swift 파일에는 PerfectHTTP의 routes를 정의하고 리턴하는 클레스를 작성할 예정입니다.

Handlers.swift 파일에는 각 route에 해당하는 method들을 작성할 예정입니다.

$ cd ./Sources/nGleServer005/
$ touch Routes.swift
$ touch Handlers.swift
$ cd ../..
$ swift package generate-xcodeproj
$ open nGleServer005.xcodeproj/

다시 xcodeproj로 변환하고 xcode에서 보면 파일이 추가된 것을 확인 할 수 있습니다.


main.swift에 다음과 같이 추가합니다.

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import PerfectSession
import PerfectSessionRedis
import PerfectRedis

RedisSessionConnector.host = "192.168.0.188"
RedisSessionConnector.password = "ngleredis1234"
RedisSessionConnector.port = redisDefaultPort

let server = HTTPServer()

SessionConfig.name = "TestingRedisDrivers"
SessionConfig.idle = 60

// Optional
SessionConfig.cookieDomain = "localhost"
SessionConfig.IPAddressLock = true
SessionConfig.userAgentLock = true
SessionConfig.CSRF.checkState = true

SessionConfig.CORS.enabled = true
SessionConfig.CORS.acceptableHostnames.append("http://www.test-cors.org")
//SessionConfig.CORS.acceptableHostnames.append("*.test-cors.org")
SessionConfig.CORS.maxAge = 60


let sessionDriver = SessionRedisDriver()

server.setRequestFilters([sessionDriver.requestFilter])
server.setResponseFilters([sessionDriver.responseFilter])

server.addRoutes(nGle005Routes())
server.serverPort = 8181

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

Routes.swift 파일입니다.

import PerfectLib
import PerfectHTTP

public func nGle005Routes() -> Routes {
    var routes = Routes()

    routes.add(method: .get, uri: "/", handler: WebHandlers.indexHandlerGet)
    routes.add(method: .get, uri: "/json", handler: WebHandlers.indexHandlerGetJSON)
    routes.add(method: .get, uri: "/nocsrf", handler: WebHandlers.formNoCSRF)
    routes.add(method: .get, uri: "/withcsrf", handler: WebHandlers.formWithCSRF)
    routes.add(method: .post, uris: ["/nocsrf", "/withcsrf"], handler: WebHandlers.formReceive)

    // for CORS
    routes.add(method: .get, uri: "/cors", handler: WebHandlers.CORSHandlerGet)

    return routes
}

Handler.swift 파일입니다.

import PerfectLib
import PerfectHTTP
import PerfectSession
import PerfectSessionRedis
import PerfectRedis

public class WebHandlers {

    /* =================================================================================================================
     Index
     ================================================================================================================= */
    open static func indexHandlerGet(request: HTTPRequest, _ response: HTTPResponse) {

        var dump = ""
        do {
            let x = request.session?.data
            dump = try x.jsonEncodedString()
        } catch {
            dump = "\(error)"
        }
        var body = "

Your Session ID is: \(request.session?.token ?? "")

Session data: \(dump)

" body += "

CSRF Test Form

" body += "

No CSRF Test Form

" response.setBody(string: header+body+footer) response.completed() } /* ================================================================================================================= Index ================================================================================================================= */ open static func indexHandlerGetJSON(request: HTTPRequest, _ response: HTTPResponse) { var opt = [String: Any]() opt["sessionid"] = request.session?.token opt["dump"] = request.session?.data _ = try? response.setBody(json: opt) response.completed() } /* ================================================================================================================= CORS ================================================================================================================= */ open static func CORSHandlerGet(request: HTTPRequest, _ response: HTTPResponse) { response.addHeader(.contentType, value: "application/json") let _ = try? response.setBody(json: ["Success":"CORS Request"]) response.completed() } /* ================================================================================================================= formNoCSRF ================================================================================================================= */ open static func formNoCSRF(request: HTTPRequest, _ response: HTTPResponse) { var body = "

Your Session ID is: \(request.session?.token ?? "")

" body += "

No CSRF Form

" body += "

NOTE: You should get a failed request because there is no CSRF

" body += "

" body += "

" body += "
" response.setBody(string: header+body+footer) response.completed() } /* ================================================================================================================= formWithCSRF ================================================================================================================= */ open static func formWithCSRF(request: HTTPRequest, _ response: HTTPResponse) { let t = request.session?.data["csrf"] as? String ?? "" var body = "

Your Session ID is: \(request.session?.token ?? "")

" body += "

CSRF Form

" body += "

" body += "

" body += "

" body += "
" response.setBody(string: header+body+footer) response.completed() } /* ================================================================================================================= formReceive ================================================================================================================= */ open static func formReceive(request: HTTPRequest, _ response: HTTPResponse) { // print("in formReceive") var body = "

Your Session ID is: \(request.session?.token ?? "")

" body += "

CSRF Test response

" body += "

Params: \(request.postParams)

" response.setBody(string: header+body+footer) response.completed() } static var header = "<html><head><link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" integrity=\"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u\" crossorigin=\"anonymous\"><title>Perfect Sessions Demo</title><style>.header,body{padding-bottom:20px}.header,.jumbotron{border-bottom:1px solid #e5e5e5}body{padding-top:20px}.footer,.header,.marketing{padding-right:15px;padding-left:15px}.header h3{margin-top:0;margin-bottom:0;line-height:40px}.footer{padding-top:19px;color:#777;border-top:1px solid #e5e5e5}@media (min-width:768px){.container{max-width:730px}}.container-narrow>hr{margin:30px 0}.jumbotron{text-align:center}.jumbotron .btn{padding:14px 24px;font-size:21px}.marketing{margin:40px 0}.marketing p+h4{margin-top:28px}@media screen and (min-width:768px){.footer,.header,.marketing{padding-right:0;padding-left:0}.header{margin-bottom:30px}.jumbotron{border-bottom:0}}</style></head><body><div class=\"container\"><div class=\"header clearfix\"><h3 class=\"text-muted\"><a href=\"/\">Perfect Sessions Demo</a></h3></div>" static var footer = "</div></body></html>" }

xcode에서 실행 후 브라우저를 열고 localhost:8181을 호출하면 아래와 같이 서버에 접속한 Session 정보를 볼수 있습니다.


Redis에 접속해 Session ID가 추가되었는지 확인해 봅시다.

127.0.0.1:6379> keys *
1) "7683CBB2-5F2B-44E9-A594-F65F201B860D"

여기까지는 Perfect-Session-Redis-Demo의 내용이었습니다.

다음 Post에서 Redis의 Set, Get을 구현해 보겠습니다.



Comments