From 71e3db08576d46908870752639c50bcdce6fa593 Mon Sep 17 00:00:00 2001 From: landrigun Date: Mon, 10 Oct 2022 14:59:29 +0000 Subject: [PATCH] feat: #12 add async block in handlers (more readable) + fix tests --- src/http/response.rs | 3 +-- src/http/router.rs | 48 +++++++++++++++++++++++++---------- tests/bash/curling.bash | 2 +- tests/python/test_requests.py | 15 ++++++----- 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/http/response.rs b/src/http/response.rs index 166fc80..0f0b436 100644 --- a/src/http/response.rs +++ b/src/http/response.rs @@ -1,6 +1,5 @@ //! response handles the incoming request parsed `HTTPRequest` -//! it will check if the `HTTPRequest` is valid and build an HTTPResponse corresponding to the HTTP -//! message specs. see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages +//! it will build an HTTPResponse corresponding to the HTTP message specs. see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages //! NOTE: only few parts of the specification has been implemented use crate::http::request::HTTPVersion; diff --git a/src/http/router.rs b/src/http/router.rs index f6191bb..50a61ca 100644 --- a/src/http/router.rs +++ b/src/http/router.rs @@ -12,28 +12,48 @@ use std::pin::Pin; type FuturePinned = Pin>>; type Handler = fn(HTTPRequest) -> FuturePinned; -async fn handle_get(request: HTTPRequest) -> HTTPResponse { - // TODO: path to `store.txt` must not be hardcoded, should be in a config file and load at runtime - let mut store = FileStore::new("tests/data/store.txt".to_string()); - match request.body { - Some(ref b) => { - let is_auth = store.is_auth(&b.get_data()).await; - if !is_auth { - return HTTPResponse::as_403(); +fn handle_get(request: HTTPRequest) -> FuturePinned { + Box::pin(async move { + // TODO: path to `store.txt` must not be hardcoded, should be in a config file and load at runtime + let mut store = FileStore::new("tests/data/store.txt".to_string()); + match &request.body { + Some(ref b) => { + let is_auth = store.is_auth(&b.get_data()).await; + if !is_auth { + return HTTPResponse::as_403(); + } + HTTPResponse::as_200() } - HTTPResponse::as_200() + None => HTTPResponse::as_400(), } - None => HTTPResponse::as_400(), - } + }) } -fn handle_get_pinned(request: HTTPRequest) -> FuturePinned { - Box::pin(handle_get(request)) +/// validates the token by checking: +/// * expiration time +fn handle_validate(request: HTTPRequest) -> FuturePinned { + Box::pin(async move { + match &request.body { + Some(ref _b) => { + // TODO: impl the JWT validation + HTTPResponse::as_200() + } + None => HTTPResponse::as_400(), + } + }) } lazy_static! { + /// defines the map between the URL and its associated callback + /// each authorized targets must implement a function returning `FuturePinned` + // TODO: a macro should be implemented to mask the implementation details static ref HTTP_METHODS: HashMap<&'static str, Handler> = - HashMap::from([("/get/", handle_get_pinned as Handler),]); + HashMap::from( + [ + ("/get/", handle_get as Handler), + ("/validate/", handle_validate as Handler) + ] + ); } pub struct Router; diff --git a/tests/bash/curling.bash b/tests/bash/curling.bash index d144993..5642cca 100755 --- a/tests/bash/curling.bash +++ b/tests/bash/curling.bash @@ -28,7 +28,7 @@ done for i in {0..10} do http_response=$(curl -s -o response.txt -w "%{http_code}" ${URL}/ge/ -d '{"username":"toto", "password":"tutu"}') - if [ $http_response != "400" ] + if [ $http_response != "404" ] then echo "bad http status code : ${http_response}, expect 400" exit 1 diff --git a/tests/python/test_requests.py b/tests/python/test_requests.py index d17f41e..20e8409 100644 --- a/tests/python/test_requests.py +++ b/tests/python/test_requests.py @@ -26,23 +26,26 @@ class TestResponse(TestCase): resp.json()["token"], "header.payload.signature", "bad status returned" ) + # TODO: must be updated after implmenting `/refresh/` url handler def test_refresh_target(self): resp = requests.post( URL + "/refresh/", json={"username": "toto", "password": "tata"} ) - self.assertEqual(resp.status_code, 200, "bad status code returned") + self.assertEqual(resp.status_code, 404, "bad status code returned") self.assertIsNotNone(resp.json(), "response data can't be empty") self.assertEqual( - resp.json()["token"], "header.payload.signature", "bad status returned" + resp.json()["error"], + "the url requested does not exist", + "bad status returned", ) def test_no_credentials(self): resp = requests.post(URL + "/get/") - self.assertEqual(resp.status_code, 403, "bad status code returned") + self.assertEqual(resp.status_code, 400, "bad status code returned") self.assertIsNotNone(resp.json(), "response data must not be empty") self.assertEqual( resp.json()["error"], - "invalid credentials", + "the incoming request is not valid", "invalid error message returned", ) @@ -62,10 +65,10 @@ class TestResponse(TestCase): resp = requests.post( URL + "/token/", json={"username": "toto", "password": "tata"} ) - self.assertEqual(resp.status_code, 400, "bad status code returned") + self.assertEqual(resp.status_code, 404, "bad status code returned") self.assertIsNotNone(resp.json(), "response data must not be empty") self.assertEqual( resp.json()["error"], - "the incoming request is not valid", + "the url requested does not exist", "invalid error message returned", )