iyOmSd/Title: Vapor

[Vapor] Routing (경로 설정, Data받아오기)

냄수 2021. 3. 6. 14:47
반응형

Vapor버전 4.0을 기준으로 작성된 게시글입니다!

 

 

HTTP Method에는

get - read

post - create

put - replace

patch - update

delete - delete

가 있어요

 

이러한 통신규약을 통한 통신을 만들어볼거에요

    //http://127.0.0.1:8080/hello/vapor
    app.get("hello", "vapor") { req in
        return "Hello, vapor!"
    }
    
    //http://127.0.0.1:8080/hello/vapor
    app.on(.GET, "hello", "vapor") { req in
        return "on hello vapor"
    }

 

app.get - get에 특화된 함수

app.on(HTTPMethod) - 메소드를 설정해주는 함수

크게 두가지 형식이 있구요

같은 동작을하는데 취향에 따라 사용하는게 다를것 같네요

 

그리고 위와같이

,(콤마)로 경로를 나열해요

위에서

app.get("hello", "vapor") 이런 함수를 만들었다면

localhost:8080/hello/vapor 이렇게 경로에 하나씩 들어가요

 

또 경로를 설정하는 방법중 편리하다고 생각하는게 있는데

group 기능이에요

같은 경로를 묶어주는 기능이죠

 

path prefix라고하는것 같아요

 

사용하는 방법에는 여러 방법이 있어서 

취향대로 사용하면 될 것 같아요

 

방법1

let users = app.grouped("users")
// GET /users
users.get { req in
    ...
}
// POST /users
users.post { req in
    ...
}
// GET /users/:id
users.get(":id") { req in
    let id = req.parameters.get("id")!
    ...
}

 

방법2

app.group("users") { users in
    // GET /users
    users.get { req in
        ...
    }
    // POST /users
    users.post { req in
        ...
    }
    // GET /users/:id
    users.get(":id") { req in
        let id = req.parameters.get("id")!
        ...
    }
}

 

방법3

app.group("users") { users in
    // GET /users
    users.get { ... }
    // POST /users
    users.post { ... }

    users.group(":id") { user in
        // GET /users/:id
        user.get { ... }
        // PATCH /users/:id
        user.patch { ... }
        // PUT /users/:id
        user.put { ... }
    }
}

 

 

이런 경로만 쓰기도하지만 요청에 추가적인 파라미터도 보내서 그값에 해당하는 응답을 받기도하죠?

 

요청을 할때 데이터를 같이 보내는 방법엔

 

1. 패스에 넣어서보내기(foo/who)

2. URL Query형식(foo?name="who"& 사용)

3. body사용

이 있죠

 

Path Parameter

패스처럼 파라미터를 넣어서 요청할 수 있는 형식이에요

:foo 형식이에요(콜론 + 요청파라미터)

    // http://127.0.0.1:8080/hello/ns
    app.get("hello", ":name") { req -> String in
        let name = req.parameters.get("name")!
        return "Hello, \(name)!"
    }
    
    app.get("hello", "**") { req -> String in
        let name = req.parameters.getCatchall().joined(separator: " ")
        return "Hello, \(name)!"
    }

위처럼 "hello", ":name"으로 만들면

localhost:8080/hello/ns 라고하면 

이 값을

서버에서

req.parameters.get["name"]으로 접근해올 수 있어요

이 값은 ns가 나오겠죠

 

* 형식은

와일드카드처럼 아무 값이나 와도 상관없는 경로를 뜻해요

 

** 형식은

Catchall 이라고 불리고

해당 경로위치이후에 뭐가오든 상관없이 동작해요

localhost:8080/hello/foo

localhost:8080/hello/foo/one

localhost:8080/hello/foo/one/two

모두 같은 함수가 실행되는거죠

req.parameters.getCatchall()로 경로에 들어간 문자열배열을 반환받을 수 있어요

 

 

URL Query

// http://127.0.0.1:8080/hello?name="hi"
    app.get("hello") { req -> String in
        let hello = try req.query.decode(Hello.self)
        return "url query: Hello \(hello.name ?? "Anonymous")"
        // url query: Hello "hi"
    }
    
    app.get("hello") { req -> String in
        let name: String? = req.query["name"]
        return "url query: Hello \(name ?? "Anonymous")"
        // url query: Hello "hi"
    }
    
    
struct Hello: Content {
    var name: String?
}

path설정만 해주고

URL Query로 날라올 것들은

req.query

로 접근해서 사용해요

위에서 req.query["name"] 이있다면

localhost:/8080/hello?name="~~" 에서 ~~에 접근할 수 있어요

 

이렇게 딕셔너리형태로 바로 접근할 수도 있지만

decode를 통해서 만들어둔 구조체로 바로 변환 할 수도 있어요

 

Content라는 타입이구요

HTTP 메세지를 쉽게 인코딩/디코딩 할 수 있도록 도와주는 타입이에요

Content가 Codable을 채택하고있어서 디코드에 문제가없어요

 

Body

우선 Body를 사용하려면

Get이아닌 Post형식을 사용해야겠죠

/* 요청
POST /greeting HTTP/1.1
content-type: application/json
content-length: 18

{"hello": "world"}
*/
struct Greeting: Content {
    var hello: String
}

app.post("greeting") { req in 
    let greeting = try req.content.decode(Greeting.self)
    print(greeting.hello) // "world"
    return HTTPStatus.ok
}

body에 ["hello": "world"] 를 담아서 보냈다면

접근할땐

req.content

로 접근해요

원하는 값만 딕셔너리로 빼올수도있고 디코드를 사용해서 구조체로 변환할 수도 있어요

 

 

반응형