Closed nabetti1720 closed 2 months ago
We will continue to address the following points:
We have revised our policy a bit.
- Return network error response.
Since it has already been pointed out in the review that simply returning an Error is sufficient, we are not going to do this in the immediate future.
If necessary, we would like to implement a method to generate and return a Network error response by calling something like Response::error(ctx)
.
- Replace only the url when build_request() is called multiple times.
Reading through the HTTP-redirect fetch, we see that we need to control multiple request parameters, not just the url, depending on the method and status code.
To control this, we would like to keep the build_request()
to generate the next request parameter.
After this, commit additional modifications.
- Add test code
I am wondering if it is possible to do a fetch()
redirect test without accessing the actual site. Any good ideas?
Note that the minimum test for the pattern necessary to make a decision was implemented in rust.
Thanks again for the PR. I think it LGTM. 🚀
We have revised our policy a bit.
- Return network error response.
Since it has already been pointed out in the review that simply returning an Error is sufficient, we are not going to do this in the immediate future. If necessary, we would like to implement a method to generate and return a Network error response by calling something like
Response::error(ctx)
.
What value would this bring?
- Replace only the url when build_request() is called multiple times.
Reading through the HTTP-redirect fetch, we see that we need to control multiple request parameters, not just the url, depending on the method and status code. To control this, we would like to keep the
build_request()
to generate the next request parameter. After this, commit additional modifications.
You can ignore the “cors” logic as it’s mainly relevant to browsers and is not planned to be supported.
- Add test code
I am wondering if it is possible to do a
fetch()
redirect test without accessing the actual site. Any good ideas? Note that the minimum test for the pattern necessary to make a decision was implemented in rust.
Yes, runtime_client.rs has tests using wiremock: https://github.com/awslabs/llrt/blob/bfaa41ecd20df9de971aa0358571e30c2a46ae3f/src/runtime_client.rs#L500
Thanks again for the PR. I think it LGTM. 🚀
We have revised our policy a bit.
- Return network error response.
Since it has already been pointed out in the review that simply returning an Error is sufficient, we are not going to do this in the immediate future. If necessary, we would like to implement a method to generate and return a Network error response by calling something like
Response::error(ctx)
.What value would this bring?
Yes, I have not found a use case for llrt
at this time. So I do not think that implementation is necessary.
- Replace only the url when build_request() is called multiple times.
Reading through the HTTP-redirect fetch, we see that we need to control multiple request parameters, not just the url, depending on the method and status code. To control this, we would like to keep the
build_request()
to generate the next request parameter. After this, commit additional modifications.You can ignore the “cors” logic as it’s mainly relevant to browsers and is not planned to be supported.
Understood. So, would it be safe to assume that we have roughly completed the implementation? Please point out any specifications that are of concern.
- Add test code
I am wondering if it is possible to do a
fetch()
redirect test without accessing the actual site. Any good ideas? Note that the minimum test for the pattern necessary to make a decision was implemented in rust.Yes, runtime_client.rs has tests using wiremock:
Thank you for sharing your excellent samples! This is the first implementation I've seen, so it may take some time, but I'll get to work on creating a mock server as soon as possible :)
I am creating a test with a mock server as soon as possible, but the fetch()
call part is not working properly.
I am thinking of using fetch()
defined in the globals
of vm
. Is the procedure correct?
let vm = Vm::new().await.unwrap();
async_with!(vm.ctx => |ctx| {
async move {
let result = ctx.globals().fetch(format!("http://{}/expect/200/", mock_server.address()), None).await;
assert!(result.is_ok());
}
})
.await;
vm.runtime.idle().await;
error[E0599]: no method named `fetch` found for struct `rquickjs::Object<'_>` in the current scope
--> src/http/fetch.rs:490:44
|
490 | let result = ctx.globals().fetch(format!("http://{}/expect/200/", mock_server.address()), None).await;
| ^^^^^ method not found in `Object<'_>`
ctx.globals().fetch(
You would have to access the global object like this:
let fetch = ctx.globals().get("fetch")?;
let res: Promise<Value> = fetch(....)?;
let response = res.await?;
My apologies. I have tried everything, but I cannot resolve the error that the type of fetch is not specified. What is the type of fetch in this case?
let vm = Vm::new().await.unwrap();
async_with!(vm.ctx => |ctx| {
async move {
let fetch = ctx.globals().get("fetch")?;
let res: Promise<Value> = fetch(format!("http://{}/expect/200/", mock_server.address()), None)?;
let response = res.await?;
assert!(response.is_ok());
Ok(())
}
})
.await;
vm.runtime.idle().await;
error[E0282]: type annotations needed
--> src/http/fetch.rs:490:21
|
490 | let fetch = ctx.globals().get("fetch")?;
| ^^^^^
491 | let res: Promise<Value> = fetch(format!("http://{}/expect/200/", mock_server.address()), None)?;
| -------------------------------------------------------------------- type must be known at this point
|
help: consider giving `fetch` an explicit type
|
490 | let fetch: /* Type */ = ctx.globals().get("fetch")?;
| ++++++++++++
My apologies. I have tried everything, but I cannot resolve the error that the type of fetch is not specified. What is the type of fetch in this case?
No need to apologize. Fetch is a Function
:)
let fetch: Function = ...
And you call it like this:
fetch.call((url, options))?; //send tuple as argument
We are continuing to try things, but there are two issues.
assert!
in `async_with!, I get an error. Therefore, I am wondering if it is possible to bring the response outside. In addition, what should be done to determine when an exception occurs?response
as in fetch
? (Issue No. 1 has not been resolved and not confirmed.)let vm = Vm::new().await.unwrap();
async_with!(vm.ctx => |ctx| {
async move {
let fetch: Function = ctx.globals().get("fetch")?;
let url = format!("http://{}/expect/200/", mock_server.address());
let options = {};
let res: Promise<Value> = fetch.call((url, options))?;
let response = res.await?;
// The assert macro cannot be used in asynchronous functions.
// assert!(response.is_ok());
Ok(())
}
})
.await;
vm.runtime.idle().await;
error[E0282]: type annotations needed
--> src/http/fetch.rs:497:17
|
497 | Ok(())
| ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
|
help: consider specifying the generic arguments
|
497 | Ok::<(), E>(())
| +++++++++
We are continuing to try things, but there are two issues.
- When I try to use
assert!
in `async_with!, I get an error. Therefore, I am wondering if it is possible to bring the response outside. In addition, what should be done to determine when an exception occurs?
Yes, you can return the result from the await right away:
let fetch_result: Result<Value> = async_with!(vm.ctx => |ctx| {
async move {
...
let res: Promise<Value> = fetch.call((url, options))?;
res.await.catch(&ctx).unwrap()
}}).await;
let fetch_response = Class::<Response>::from_value(fetch_result.unwrap()).unwrap();
let response = fetch_response.borrow();
assert!(response.status,200) //etc
...
Yes, you can return the result from the await right away:
I'm sorry. I continue to have trouble getting res out of the async block. I asked ChatGPT and got several suggestions for how to write L494, but they were all no good...
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/http/fetch.rs:490:65
|
489 | / async move {
490 | | let fetch: Function = ctx.globals().get("fetch")?;
| | ^ cannot use the `?` operator in an async block that returns `rquickjs::Value<'_>`
491 | | let url = format!("http://{}/expect/200/", mock_server.address());
492 | | let options = {};
493 | | let res: Promise<Value> = fetch.call((url, options))?;
494 | | res.await.catch(&ctx).unwrap()
495 | | }}).await;
| |_____________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<std::result::Result<Infallible, rquickjs::Error>>` is not implemented for `rquickjs::Value<'_>`
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> src/http/fetch.rs:493:69
|
489 | / async move {
490 | | let fetch: Function = ctx.globals().get("fetch")?;
491 | | let url = format!("http://{}/expect/200/", mock_server.address());
492 | | let options = {};
493 | | let res: Promise<Value> = fetch.call((url, options))?;
| | ^ cannot use the `?` operator in an async block that returns `rquickjs::Value<'_>`
494 | | res.await.catch(&ctx).unwrap()
495 | | }}).await;
| |_____________- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `FromResidual<std::result::Result<Infallible, rquickjs::Error>>` is not implemented for `rquickjs::Value<'_>`
error[E0308]: mismatched types
--> src/http/fetch.rs:488:43
|
488 | let fetch_result: Result<Value> = async_with!(vm.ctx => |ctx| {
| ____________________________________________^
489 | |/ async move {
490 | || let fetch: Function = ctx.globals().get("fetch")?;
491 | || let url = format!("http://{}/expect/200/", mock_server.address());
492 | || let options = {};
493 | || let res: Promise<Value> = fetch.call((url, options))?;
494 | || res.await.catch(&ctx).unwrap()
495 | || }}).await;
| ||_____________-_^ expected `Result<Value<'_>, Error>`, found `async` block
| |_____________|
| the found `async` block
|
= note: expected enum `std::result::Result<rquickjs::Value<'_>, rquickjs::Error>`
found `async` block `{async block@src/http/fetch.rs:489:13: 495:14}`
= note: this error originates in the macro `async_with` (in Nightly builds, run with -Z macro-backtrace for more info)
Sorry my misstake, I forgot to remove unwrap
. You need to do that if you want to return Result using ?
from the async block. Options is also wrong here: {}
in rust is a closure, not a JS object. You can pass a Request
object or a JS object like this:
let options = Object::new(ctx).unwrap();
options.set("redirect","manual").unwrap();
//etc
let fetch_result: Result<Value> = async_with!(vm.ctx => |ctx| {
async move {
let fetch: Function = ctx.globals().get("fetch")?;
let url = format!("http://{}/expect/200/", mock_server.address());
let res: Promise<Value> = fetch.call((url, options))?;
res.await.catch(&ctx)
}}).await;
Sorry my misstake, I forgot to remove
unwrap
. You need to do that if you want to return Result using?
from the async block. Options is also wrong here:{}
in rust is a closure, not a JS object. You can pass aRequest
object or a JS object like this:
Thank you very much. However, when creating the initial object for the options
, it seems that ctx
is not allowed in this position because of the AsyncContext
.
I also removed the unwrap()
on the last line of the async
block, but the error did not change significantly.
The codes and errors at this time are as follows.
let vm = Vm::new().await.unwrap();
let fetch_result: Result<Value> = async_with!(vm.ctx => |ctx| {
async move {
let fetch: Function = ctx.globals().get("fetch")?;
let options = Object::new(ctx).unwrap();
options.set("redirect","manual").unwrap();
let url = format!("http://{}/expect/200/", mock_server.address());
let res: Promise<Value> = fetch.call((url, options))?;
res.await.catch(&ctx)
}}).await;
let fetch_response = Class::<Response>::from_value(fetch_result.unwrap()).unwrap();
let response = fetch_response.borrow();
assert!(response.status() == 200);
vm.runtime.idle().await;
error[E0277]: `?` couldn't convert the error to `CaughtError<'_>`
--> src/http/fetch.rs:490:65
|
490 | let fetch: Function = ctx.globals().get("fetch")?;
| ^ the trait `std::convert::From<rquickjs::Error>` is not implemented for `CaughtError<'_>`, which is required by `std::result::Result<rquickjs::Value<'_>, CaughtError<'_>>: FromResidual<std::result::Result<Infallible, rquickjs::Error>>`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the following other types implement trait `FromResidual<R>`:
<std::result::Result<T, F> as FromResidual<Yeet<E>>>
<std::result::Result<T, F> as FromResidual<std::result::Result<Infallible, E>>>
= note: required for `std::result::Result<rquickjs::Value<'_>, CaughtError<'_>>` to implement `FromResidual<std::result::Result<Infallible, rquickjs::Error>>`
error[E0277]: `?` couldn't convert the error to `CaughtError<'_>`
--> src/http/fetch.rs:496:69
|
496 | let res: Promise<Value> = fetch.call((url, options))?;
| ^ the trait `std::convert::From<rquickjs::Error>` is not implemented for `CaughtError<'_>`, which is required by `std::result::Result<rquickjs::Value<'_>, CaughtError<'_>>: FromResidual<std::result::Result<Infallible, rquickjs::Error>>`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the following other types implement trait `FromResidual<R>`:
<std::result::Result<T, F> as FromResidual<Yeet<E>>>
<std::result::Result<T, F> as FromResidual<std::result::Result<Infallible, E>>>
= note: required for `std::result::Result<rquickjs::Value<'_>, CaughtError<'_>>` to implement `FromResidual<std::result::Result<Infallible, rquickjs::Error>>`
error[E0308]: mismatched types
--> src/http/fetch.rs:488:43
|
488 | let fetch_result: Result<Value> = async_with!(vm.ctx => |ctx| {
| ____________________________________________^
489 | |/ async move {
490 | || let fetch: Function = ctx.globals().get("fetch")?;
491 | || let options = Object::new(ctx).unwrap();
492 | || options.set("redirect","manual").unwrap();
... ||
497 | || res.await.catch(&ctx)
498 | || }}).await;
| ||_____________-_^ expected `Result<Value<'_>, Error>`, found `async` block
| |_____________|
| the found `async` block
|
= note: expected enum `std::result::Result<rquickjs::Value<'_>, rquickjs::Error>`
found `async` block `{async block@src/http/fetch.rs:489:13: 498:14}`
= note: this error originates in the macro `async_with` (in Nightly builds, run with -Z macro-backtrace for more info)
The following lines are also available in ?
-> .unwrap()
, the error that occurred in this line disappeared.
... let fetch: Function = ctx.globals().get("fetch")?; ... let res: Promise<Value> = fetch.call((url, options))?; ...
I cannot resolve the L497 error. Regardless of the contents of L497, the same error always occurs.
The error message is,
expected `Result<Value<'_>, Error>`, found `async` block
so it looks like I need to implement something that returns Result<Value<'_>, Error>
after async
block.
No more pseudo code! I've tested this and it compiles. We make all the assertions inside the async block and catch the exceptions inside the async_with! macro as they can't be returned outside of it.
async_with!(vm.ctx => |ctx| {
let globals = ctx.globals();
let run = async {
let options = Object::new(ctx.clone())?;
options.set("redirect", "manual")?;
let fetch: Function = globals.get("fetch")?;
let url = format!("http://{}/expect/200/", "url");
let response_promise: Promise<Value> = fetch.call((url,options))?;
let response = response_promise.await?;
let response = Class::<Response>::from_value(response)?;
let response = response.borrow();
//do more tests and assertions in here
assert_eq!(response.status(),200);
Ok(())
};
run.await.catch(&ctx).unwrap();
})
.await;
Hi @richarddavison, Thank you for your dedication and support!
Finally, the cargo test
started to pass when accessing the mock server I created.
Issue # (if available)
340
Description of changes
Checklist
tests/unit
and/or in Rust for my feature if neededmake fix
to format JS and apply Clippy auto fixesmake check
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.