Rust + Warp 4가 포함된 REST API: PUT 및 DELETE

19349 단어 rustrestwarpapi
그게 다야, 마지막 방법. 처음에는 시리즈가 끝날 줄 알았는데 curl 를 사용하여 수동으로 테스트하는 방법에 대한 추가 게시물이 필요하다는 것을 깨달았습니다. 그러나 그 전에 코딩해야 할 두 가지 방법이 더 있습니다. 그러나 걱정하지 마십시오. 두 가지를 결합하면 지금까지 처리한 단일 항목보다 더 쉬울 것입니다.


워프 4, 술루 씨.



The code for this part is available .


PUT 메서드는 삽입과 변경을 혼합한 것입니다. 데이터가 없을 때 항목을 생성하고 데이터가 있을 때 업데이트합니다.

이 동작은 이미 HashSet에 의해 충족됩니다. 이것이 바로 insert() 함수가 작동하는 방식입니다. 그러나 반환되는 상태가 달라야 삽입 또는 변경하는지 알 수 있습니다.
  • 생성 시 코드 201
  • 업데이트 시 코드 200

  • 나는 이것을 어디에서 얻었습니까? 라고 쓰여 있습니다here.

    이를 염두에 두고 다음 코드를 작성했습니다.

    #[tokio::test]
    async fn try_update() {
        let db = models::new_db();
        let api = filters::update_sim(db);
    
        let response = request()
            .method("PUT")
            .path("/holodeck/1")
            .json(&models::Name{ new_name: String::from("The Big Goodbye")})
            .reply(&api)
            .await;
    
        assert_eq!(response.status(), StatusCode::CREATED);
    
        let response = request()
            .method("PUT")
            .path("/holodeck/1")
            .json(&models::Name{ new_name: String::from("The Short Hello")})
            .reply(&api)
            .await;
    
        assert_eq!(response.status(), StatusCode::OK);
    }
    


    201이 StatusCode::CREATED이고 200이 StatusCode::OK라는 것을 어떻게 알았습니까? Here .

    보시다시피 request는 매개변수 id(이 경우 "1")를 전송하여 만들어집니다. GET 와 달리 이 매개변수는 필수입니다. 그리고 id가 이미 URI로 전송되고 있기 때문에 본문에는 name만 포함됩니다. 이에 대한 근거는 앞서 언급한 rfc에도 있습니다.

    이 때문에 JSON 본문을 얻기 위해 새로운 구조체와 새로운 함수를 구현했습니다.

    #[derive(Debug, Deserialize, Serialize)]
    pub struct NewName{ pub name: String }
    



    // This code is inside the mod "filters"
    fn json_body_put() -> impl Filter<Extract = (models::NewName,), Error = warp::Rejection> + Clone {
        warp::body::content_length_limit(1024 * 16).and(warp::body::json())
    }
    


    이것은 확실히 차선책입니다. 하지만 어쨌든 계속 가자. 일이 잘 풀리지 않는다는 핑계는 마지막까지 아껴두겠습니다.

    이제 필터와 핸들러입니다.

    // This is inside the mod "filters"
    pub fn update_sim(db: models::Db) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
        let db_map = warp::any()
            .map(move || db.clone());
    
        warp::path!("holodeck" / u64)
            .and(warp::put())
            .and(json_body_put())
            .and(db_map)
            .and_then(handlers::handle_update_sim)
    }
    



    pub async fn handle_update_sim(id: u64, new: models::NewName, db: models::Db) -> Result<impl warp::Reply, Infallible> {
        // Replaced entry
        if let Some(_) = db.lock().await.replace(Simulation{id, name: new.name}){
            return Ok(warp::reply::with_status(
                format!("Simulation #{} was updated.\n", id), 
                StatusCode::OK,
            ));
        }
    
        // Create entry
        Ok(warp::reply::with_status(
            format!("Simulation #{} was inserted.\n", id), 
            StatusCode::CREATED,
        ))
    }
    


    그리고 그게 다야!


    적색 경보


    DELETE 메서드를 사용하여 마무리합니다.

    평소와 같이 요청은 매우 간단합니다. 본문 없이 id를 매개변수로 보냅니다. 응답으로 "representation describing the status" 을 포함하는 코드 200(OK)이 예상됩니다.

    #[tokio::test]
    async fn try_delete() {
        let simulation = models::Simulation{
            id: 1, 
            name: String::from("The Big Goodbye!"),
        };
    
        let db = models::new_db();
        db.lock().await.insert(simulation);
    
        let api = filters::delete_sim(db);
    
        let response = request()
            .method("DELETE")
            .path("/holodeck/1")
            .reply(&api)
            .await;
    
            assert_eq!(response.status(), StatusCode::OK);
    }
    


    바라건대, 필터 구현에 대한 아무 것도 당신에게 이상하게 보이지 않습니다.

    pub fn delete(db: models::Db) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
        let db_map = warp::any()
            .map(move || db.clone());
    
        warp::path!("holodeck" / u64)
            .and(warp::delete())
            .and(db_map)
            .and_then(handlers::handle_delete_sim)
    }
    


    데이터를 삭제하는 것이 처음이기 때문에 핸들러는 고유한 동작을 가지고 있지만 지금까지 수행된 것과 크게 다르지 않습니다.

    pub async fn handle_delete_sim(id: u64, db: models::Db) -> Result<impl warp::Reply, Infallible> {
        if db.lock().await.remove(&Simulation{id, name: String::new(),}){
            return Ok(warp::reply::with_status(
                format!("Simulation #{} was deleted", id), 
                StatusCode::OK,
            ))
        };
    
        Ok(warp::reply::with_status(
            format!("No data was deleted."),
            StatusCode::OK,
        ))
    }
    


    그렇게 해야...

    $ cargo test
    
    running 5 tests
    test tests::try_delete ... ok
    test tests::try_create ... ok
    test tests::try_list ... ok
    test tests::try_create_duplicates ... ok
    test tests::try_update ... ok
    
    test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
    


    그리고 그것은 했다!


    Engaging Warp의 다음 에피소드에서...



    마지막으로 마지막 부분입니다. 우리는 건설된 것과 그에 반대하는 것을 섬길 것입니다curl.

    🖖

    좋은 웹페이지 즐겨찾기