Coder Social home page Coder Social logo

rust-httpc-test's People

Contributors

cyril-marpaud avatar defic avatar eboody avatar jamesguthrie avatar jeremychone avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

rust-httpc-test's Issues

reponse - incomplete match on `application/json`

Problem

If the content type is not precisely application/json the response is not recognize a json.

This is wrong as encoding can/should be used as well (e.g., application/json; utf8)

Solution

As with text matching, just do a starts_with("application/json") match.

Patch is mapped to Put

Problem

	pub async fn do_patch(&self, url: &str, content: impl Into<PostContent>) -> Result<Response> {
		self.do_push(Method::PUT, url, content.into()).await
	}

The client doesn't obey set-cookie with empty value.

I am trying to follow this tutorial. I decided to go one tiny inch beyond what is done in the video and implemented a logout route that is supposed to delete the auth cookie. It seems to work OK on the server side, i.e. the server sends a correct empty-valued, expired-last-year set-cookie directive in order to delete the cookie:

->> HANDLER      - api_logout
->> RES_MAPPER   - main_response_mapper


=== Response for POST http://localhost:8080/api/logout
=> Status         : 200 OK
=> Headers        :
   content-type: "application/json"
   content-length: "4"
   set-cookie: "auth-token=; Max-Age=0; Expires=Tue, 24 May 2022 23:05:08 GMT"
   date: "Wed, 24 May 2023 23:05:08 GMT"
=> Response Cookies:
   auth-token: 
=> Client Cookies :
   auth-token: user-1.exp.sign
=> Response Body  :
"Ok"
===

However subsequent requests made with the same client keep sending the old cookie, as if the client didn't apply the directive:

->> HANDLER      - handler_hello2 - "Rulatir"
->> RES_MAPPER   - main_response_mapper


=== Response for GET http://localhost:8080/hello/Rulatir
=> Status         : 200 OK
=> Headers        :
   content-type: "text/html; charset=utf-8"
   content-length: "30"
   date: "Wed, 24 May 2023 23:05:08 GMT"
=> Client Cookies :
   auth-token: user-1.exp.sign
=> Response Body  :
Hello <strong>Rulatir</strong>
===

I have problem with cookies in httpc-test get requests after login but I can get result with curl command.

Hi @jeremychone ,

I am using your valuable tutorial about axume and I enjoyed your httpc-test crate as well.

But when I tried to add some new nested route beside api route in your tutorial I found myself in trouble with request headers without cookie.

I added new nested route similar to your tutorial for api:

    let private_files = private_file_routes()
        .route_layer(middleware::from_fn(web::mw_auth::mw_require_auth));

    let private_files = private_file_routes()
        .route_layer(middleware::from_fn(web::mw_auth::mw_require_auth));

    let routes_apis = web::routes_tickets::routes(mc.clone())
        .route_layer(middleware::from_fn(web::mw_auth::mw_require_auth));

    let routes_all = Router::new()
        .merge(routes_hello())
        .merge(web::routes_login::routes())
        .nest("/api", routes_apis)
        .nest("/pvf", private_files)
        .layer(middleware::map_response(main_response_mapper))
        .layer(middleware::from_fn_with_state(mc.clone(), web::mw_auth::mw_ctx_resolver, ))
        .layer(CookieManagerLayer::new())
        .merge(public_no_auth_routes())
        .fallback_service(public_no_auth_routes());

async fn handler_private_file(
    ctx: Ctx,
    Path(priavate_path): Path<String>, 
) -> impl IntoResponse {
    println!("->> {:<12} - handler_private_file - {ctx:?} ", "CTX");
    println!("->> {:<12} - handler_private_file - {priavate_path:?} ", "HANDLER");

    Html(format!("bublic file requested: <strong>{priavate_path}</strong>"))
}

So when I try httpc-test:


    let hc = httpc_test::new_client("http://localhost:8080")?;

    hc.do_get("/public/lvl_01/lvl_02/public_target_at_several_level").await?.print().await?;
    hc.do_get("/public/target_at_public_root").await?.print().await?;

    // try to read private data before login:
    hc.do_get("/pvf/target_at_private_root_b4_login").await?.print().await?;
    
    let req_login = hc.do_post("/api/login", 
            json!({
                "username": "demo1",
                "pwd": "welcome"
            }));
    req_login.await?.print().await?;

    // try to read private data after login:
    hc.do_get("/pvf/lvl_01/lvl_02/private_target_at_several_level").await?.print().await?;
    hc.do_get("/pvf/private_target_at_root_level").await?.print().await?;
    
    //Check if cookies still working for api route
    hc.do_get("/api/tickets").await?.print().await?;

and here is test result:
server side log:


->> LISTENING on 127.0.0.1:8080

->> HANDLER      - handler_public_file - "lvl_01/lvl_02/public_target_at_several_level" 
->> HANDLER      - handler_public_file - "target_at_public_root" 

->> MIDDLEWARE   - mw_ctx_resolver
mw_ctx_resolver <<-- req.headers {"accept": "*/*", "host": "localhost:8080"}

mw_ctx_resolver <<-- cookies Cookies { inner: Mutex { data: Inner { headers: [], jar: None, changed: false } } }

mw_ctx_resolver -->> auth_token: None - 

->> EXTRACTOR    - Ctx
->> EXTRACTOR    - Ctx
->> MIDDLEWARE   - mw_require_auth
->> INTO_RES     - AuthFailNoAuthTokenCookie
->> RES_MAPPER   - main_response_mapper
      ->> client_error_body: {"error":{"req_uuid":"018b38f2-29c0-7aaf-9cb4-298d80d1a604","type":"NO_AUTH"}}
      ->> log_request: 
{"client_error_type":"NO_AUTH","error_type":"AuthFailNoAuthTokenCookie","req_method":"GET","req_path":"/pvf/target_at_private_root_b4_login","timestamp":"1697467476416","uuid":"018b38f2-29c0-7aaf-9cb4-298d80d1a604"}
      ->> server log line - 018b38f2-29c0-7aaf-9cb4-298d80d1a604 - Error: Some(AuthFailNoAuthTokenCookie)


->> MIDDLEWARE   - mw_ctx_resolver
mw_ctx_resolver <<-- req.headers {"content-type": "application/json", "accept": "*/*", "host": "localhost:8080", "content-length": "36"}

mw_ctx_resolver <<-- cookies Cookies { inner: Mutex { data: Inner { headers: [], jar: None, changed: false } } }

mw_ctx_resolver -->> auth_token: None - 

->> EXTRACTOR    - Ctx
->> HANDLER      - api_login
->> RES_MAPPER   - main_response_mapper
      ->> log_request: 
{"req_method":"POST","req_path":"/api/login","timestamp":"1697467476417","uuid":"018b38f2-29c1-7285-a666-c0decf982c41"}
      ->> server log line - 018b38f2-29c1-7285-a666-c0decf982c41 - Error: None


->> MIDDLEWARE   - mw_ctx_resolver
mw_ctx_resolver <<-- req.headers {"accept": "*/*", "host": "localhost:8080"}

mw_ctx_resolver <<-- cookies Cookies { inner: Mutex { data: Inner { headers: [], jar: None, changed: false } } }

mw_ctx_resolver -->> auth_token: None - 

->> EXTRACTOR    - Ctx
->> EXTRACTOR    - Ctx
->> MIDDLEWARE   - mw_require_auth
->> INTO_RES     - AuthFailNoAuthTokenCookie
->> RES_MAPPER   - main_response_mapper
      ->> client_error_body: {"error":{"req_uuid":"018b38f2-29c3-78e3-a0e7-98f5a192cee2","type":"NO_AUTH"}}
      ->> log_request: 
{"client_error_type":"NO_AUTH","error_type":"AuthFailNoAuthTokenCookie","req_method":"GET","req_path":"/pvf/lvl_01/lvl_02/private_target_at_several_level","timestamp":"1697467476419","uuid":"018b38f2-29c3-78e3-a0e7-98f5a192cee2"}
      ->> server log line - 018b38f2-29c3-78e3-a0e7-98f5a192cee2 - Error: Some(AuthFailNoAuthTokenCookie)


->> MIDDLEWARE   - mw_ctx_resolver
mw_ctx_resolver <<-- req.headers {"accept": "*/*", "host": "localhost:8080"}

mw_ctx_resolver <<-- cookies Cookies { inner: Mutex { data: Inner { headers: [], jar: None, changed: false } } }

mw_ctx_resolver -->> auth_token: None - 

->> EXTRACTOR    - Ctx
->> EXTRACTOR    - Ctx
->> MIDDLEWARE   - mw_require_auth
->> INTO_RES     - AuthFailNoAuthTokenCookie
->> RES_MAPPER   - main_response_mapper
      ->> client_error_body: {"error":{"req_uuid":"018b38f2-29c4-71bd-a26c-584b775e198b","type":"NO_AUTH"}}
      ->> log_request: 
{"client_error_type":"NO_AUTH","error_type":"AuthFailNoAuthTokenCookie","req_method":"GET","req_path":"/pvf/private_target_at_root_level","timestamp":"1697467476420","uuid":"018b38f2-29c4-71bd-a26c-584b775e198b"}
      ->> server log line - 018b38f2-29c4-71bd-a26c-584b775e198b - Error: Some(AuthFailNoAuthTokenCookie)


->> MIDDLEWARE   - mw_ctx_resolver
mw_ctx_resolver <<-- req.headers {"accept": "*/*", "cookie": "auth-token=user-1.exp.sign", "host": "localhost:8080"}

mw_ctx_resolver <<-- cookies Cookies { inner: Mutex { data: Inner { headers: ["auth-token=user-1.exp.sign"], jar: None, changed: false } } }

mw_ctx_resolver -->> auth_token: Some("user-1.exp.sign") - 

->> EXTRACTOR    - Ctx
->> EXTRACTOR    - Ctx
->> MIDDLEWARE   - mw_require_auth
->> EXTRACTOR    - Ctx
->> HANDLER      - list_tickets
->> RES_MAPPER   - main_response_mapper
      ->> log_request: 
{"req_method":"GET","req_path":"/api/tickets","timestamp":"1697467476424","user_id":1,"uuid":"018b38f2-29c8-7c01-bce9-4985a40472c0"}
      ->> server log line - 018b38f2-29c8-7c01-bce9-4985a40472c0 - Error: None

client side log:


running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


running 1 test

=== Response for GET http://localhost:8080/public/lvl_01/lvl_02/public_target_at_several_level
=> Status         : 200 OK OK
=> Headers        :
   content-type: text/html; charset=utf-8
   content-length: 84
   date: Mon, 16 Oct 2023 14:44:36 GMT
=> Response Body  :
bublic file requested: <strong>lvl_01/lvl_02/public_target_at_several_level</strong>
===


=== Response for GET http://localhost:8080/public/target_at_public_root
=> Status         : 200 OK OK
=> Headers        :
   content-type: text/html; charset=utf-8
   content-length: 61
   date: Mon, 16 Oct 2023 14:44:36 GMT
=> Response Body  :
bublic file requested: <strong>target_at_public_root</strong>
===


=== Response for GET http://localhost:8080/pvf/target_at_private_root_b4_login
=> Status         : 403 Forbidden Forbidden
=> Headers        :
   content-type: application/json
   content-length: 78
   date: Mon, 16 Oct 2023 14:44:36 GMT
=> Response Body  :
{
  "error": {
    "req_uuid": "018b38f2-29c0-7aaf-9cb4-298d80d1a604",
    "type": "NO_AUTH"
  }
}
===


=== Response for POST http://localhost:8080/api/login
=> Status         : 200 OK OK
=> Headers        :
   content-type: application/json
   content-length: 27
   set-cookie: auth-token=user-1.exp.sign
   date: Mon, 16 Oct 2023 14:44:36 GMT
=> Response Cookies:
   auth-token: user-1.exp.sign
=> Client Cookies :
   auth-token: user-1.exp.sign
=> Response Body  :
{
  "result": {
    "success": true
  }
}
===


=== Response for GET http://localhost:8080/pvf/lvl_01/lvl_02/private_target_at_several_level
=> Status         : 403 Forbidden Forbidden
=> Headers        :
   content-type: application/json
   content-length: 78
   date: Mon, 16 Oct 2023 14:44:36 GMT
=> Client Cookies :
   auth-token: user-1.exp.sign
=> Response Body  :
{
  "error": {
    "req_uuid": "018b38f2-29c3-78e3-a0e7-98f5a192cee2",
    "type": "NO_AUTH"
  }
}
===


=== Response for GET http://localhost:8080/pvf/private_target_at_root_level
=> Status         : 403 Forbidden Forbidden
=> Headers        :
   content-type: application/json
   content-length: 78
   date: Mon, 16 Oct 2023 14:44:36 GMT
=> Client Cookies :
   auth-token: user-1.exp.sign
=> Response Body  :
{
  "error": {
    "req_uuid": "018b38f2-29c4-71bd-a26c-584b775e198b",
    "type": "NO_AUTH"
  }
}
===


=== Response for GET http://localhost:8080/api/tickets
=> Status         : 200 OK OK
=> Headers        :
   content-type: application/json
   content-length: 2
   date: Mon, 16 Oct 2023 14:44:36 GMT
=> Client Cookies :
   auth-token: user-1.exp.sign
=> Response Body  :
[]
===

.
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s

now when I try same url with curl command including cookie I have correct result:

curl -v --cookie "auth-token=user-1.exp.sign" http://localhost:8080/pvf/lvl_01/lvl_02/public_target_at_several_level           17:57:09
*   Trying [::1]:8080...
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080
> GET /pvf/lvl_01/lvl_02/public_target_at_several_level HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.4.0
> Accept: */*
> Cookie: auth-token=user-1.exp.sign
> 
< HTTP/1.1 200 OK
< content-type: text/html; charset=utf-8
< content-length: 84
< date: Mon, 16 Oct 2023 14:59:25 GMT
< 
* Connection #0 to host localhost left intact
bublic file requested: <strong>lvl_01/lvl_02/public_target_at_several_level</strong>% 

So please help me find why there is no cookie in httpc-test requests when I try the other route?

How to get request's status code after a do_get ?

Is there a way to get a request's status code ? Sth that would look like this:

let client = httpc_test::new_client(format!("http://localhost:{}", axum_test::LISTENING_PORT))?;

let status_code = client.do_get("/favicon.svg").await?.status_code().await?;

I can find no status-related info on the Response documentation ๐Ÿคท

How to do a traditional POST request with form data

I love your videos, and I like this tool, but I'm working with HTMX and I need to be able to do post requests with form data.
Currently I'm trying this:

        let req_login = hc.do_post(
		"/login",
		json!({
			"username": "demo1",
			"pwd": "welcome"
		}),
	);
	req_login.await?.print().await?;

But I'm getting:

=== Response for POST http://localhost:8080/login
=> Status         : 415 Unsupported Media Type Unsupported Media Type
=> Headers        :
   content-type: text/plain; charset=utf-8
   content-length: 73
   date: Thu, 01 Feb 2024 19:06:56 GMT
=> Response Body  :
Form requests must have `Content-Type: application/x-www-form-urlencoded`
===

I don't see any related examples in the docs.

PUT elicits a POST

Great little tool - I came across it in your Axum video (which is also amazing).

Using it some scratch integration, I noticed that PUTs would fail with records already existing - poking around, it looks like it calls the request::post method instead of request::put under the hood.

Error: error sending request for url (http://localhost:8080/api/login): connection closed before message completed

Hello,

I am going through your great Axum course on Youtube and keep running up against this problem while trying to run the tests. It doesn't happen on the first test you go through (so the simple hello get request works as intended) but all the other ones after that have this issue. Using the old school curl approach to test the server works correctly as well.

I think it might have something to do with this hyper issue: hyperium/hyper#2136 but that's just a guess as you say this library is built on top of reqwest (which uses hyper right?).

Any clue how to overcome this issue? I like this workflow and would like to use it while developing my own projects. My apologies if this is something related to my system and nothing to do with your library.

p.s. Crates.io has the wrong repository link. It tried to take me here: https://github.com/rust-httpc-test

Unable to test multipart/form-data requests with httpc-test

Issue Description:

I'm currently working on a Rust backend using Actix Web, where I have implemented a POST route to handle multipart/form-data requests for saving images to disk. However, I'm encountering challenges when testing this functionality using the httpc-test library.

Issue Description:

I've created a POST route that handles multipart/form-data requests and saves images to disk, but I'm struggling to find documentation or examples on how to effectively test this route using httpc-test. I've also explored the httpc-test source code but couldn't find any solutions that suit my needs.

Request for Help:

I'm looking for guidance or examples on how to test this multipart/form-data request using httpc-test properly. Additionally, I already know how to do this using cURL, and the cURL command I use is as follows:

curl -F [email protected] http://localhost:8080/post --trace-ascii

I want a similar functionality using httpc-test

Thank you for your help in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.