Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

URI extractor fails if data struct is defined with a tuple #280

Open
llamicron opened this issue Nov 3, 2022 · 2 comments
Open

URI extractor fails if data struct is defined with a tuple #280

llamicron opened this issue Nov 3, 2022 · 2 comments

Comments

@llamicron
Copy link

llamicron commented Nov 3, 2022

If the struct that implements StateData and StaticResponseExtender used for extracting variables out of the URI is defined with a tuple, the route returns with a code 400.

Example

#[derive(Resource, serde::Deserialize)]
#[resource(update_device)]
pub struct DeviceResource;

#[derive(Debug, Deserialize, Clone, StateData, StaticResponseExtender)]
pub struct DeviceID(String); // This compiles fine, but the handler returns 400

// Replacing the above with this makes the handler return ok
// #[derive(Debug, Deserialize, Clone, StateData, StaticResponseExtender)]
// pub struct DeviceID {
//     id: String
// }

#[endpoint(
    uri = "update/:id",
    method = "Method::GET",
    params = false,
    body = false
)]
pub async fn update_device(id: DeviceID) -> Response {
    log::info!("Got id: `{:?}`", id);
    Response::no_content()
}
// Test used
// This will fail when the struct is defined as above,
// but it passes when the struct is defined with the `id` field
#[test]
    fn test_device_update() {
        let test_server = TestServer::new(router()).unwrap();
        let response = test_server
            .client()
			.get("http://localhost:7878/device/update/omega1")
            .perform()
            .unwrap();

        assert_eq!(response.status(), StatusCode::NO_CONTENT);
    }

I'm not sure if this is intentional, but it's not very clear why it fails and if that's intended behavior or not.

@msrd0
Copy link
Owner

msrd0 commented Nov 3, 2022

Try adding #[serde(transparent)] to the tuple struct. Does that fix your issue?

Sorry, this will likely not work since you're using a custom endpoint.

@msrd0
Copy link
Owner

msrd0 commented Nov 3, 2022

The struct you're defining is being used as a gotham PathExtractor which is automatically provided for all types that are Deserialize, StateData and StaticResponseExtender. When extracting a path, the deserialize implementation is provided with a map, in your case the equivalent of {"id": "omega1"}. If the deserialize implementation rejects this input, the route returns a 400. The problem is not your tuple struct but rather the auto-derived deserialize implementation for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants