Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: foxzool/bevy_http_client
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.7.0
Choose a base ref
...
head repository: foxzool/bevy_http_client
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 12 commits
  • 11 files changed
  • 2 contributors

Commits on Nov 30, 2024

  1. fix miss deps

    foxzool committed Nov 30, 2024
    Copy the full SHA
    22cb98d View commit details

Commits on Mar 24, 2025

  1. update Cargo.toml

    foxzool committed Mar 24, 2025
    Copy the full SHA
    93b2d6f View commit details

Commits on Mar 27, 2025

  1. Copy the full SHA
    4b63909 View commit details
  2. upgrade ci

    foxzool committed Mar 27, 2025
    Copy the full SHA
    e35b40c View commit details
  3. upgrade actions/cache@v4

    foxzool committed Mar 27, 2025
    Copy the full SHA
    0b1f278 View commit details

Commits on Apr 25, 2025

  1. release 0.8.0

    foxzool committed Apr 25, 2025
    Copy the full SHA
    171a750 View commit details
  2. fix cargo fmt warning

    foxzool committed Apr 25, 2025
    Copy the full SHA
    b2e0bd7 View commit details

Commits on May 26, 2025

  1. release 0.8.1

    foxzool committed May 26, 2025
    Copy the full SHA
    7d800dd View commit details

Commits on May 31, 2025

  1. access inner value T from a TypedResponse reference

    bevy EventReader.read is returning a reference, only one into_inner() method is making access inner value difficult from a reference.
    suxin1 authored May 31, 2025
    Copy the full SHA
    5bb2bd8 View commit details

Commits on Jun 3, 2025

  1. trim

    foxzool authored Jun 3, 2025
    Copy the full SHA
    b14b325 View commit details
  2. Merge pull request #11 from suxin1/master

    access inner value T from a TypedResponse reference
    foxzool authored Jun 3, 2025
    Copy the full SHA
    af1ff13 View commit details
  3. release 0.8.2

    foxzool committed Jun 3, 2025
    Copy the full SHA
    5e864ea View commit details
Showing with 190 additions and 56 deletions.
  1. +2 −2 .github/workflows/ci.yaml
  2. +16 −0 CHANGELOG.md
  3. +12 −8 Cargo.toml
  4. +17 −6 README.md
  5. +1 −1 examples/ipinfo.rs
  6. +47 −0 examples/observer.rs
  7. +1 −7 examples/typed.rs
  8. +14 −6 examples/window.rs
  9. +55 −11 src/lib.rs
  10. +1 −1 src/prelude.rs
  11. +24 −14 src/typed.rs
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ jobs:
- name: Checkout sources
uses: actions/checkout@v2
- name: Cache
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
@@ -48,7 +48,7 @@ jobs:
- name: Checkout sources
uses: actions/checkout@v2
- name: Cache
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog

## [0.8.2] - 2025-06-03

* access inner value T from a TypedResponse reference [#11](https://github.com/foxzool/bevy_http_client/pull/11)

## [0.8.1]

- add component observe

## [0.8.0]

- bump bevy version to 0.16.0

## [0.7.0] - 2024-11-30

- bump bevy version to 0.15.0

## [0.6.0] - 2024-07-05

- bump bevy version to 0.14.0
20 changes: 12 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
[package]
name = "bevy_http_client"
description = "A simple HTTP client for Bevy"
version = "0.7.0"
edition = "2021"
version = "0.8.2"
edition = "2024"
readme = "README.md"
homepage = "https://crates.io/crates/bevy_http_client"
documentation = "https://docs.rs/bevy_http_client"
repository = "https://github.com/foxzool/bevy_http_client"
authors = ["FoxZoOL <zhooul@gmail.com>"]
license = "MIT OR Apache-2.0"
@@ -12,11 +14,11 @@ keywords = ["bevy", "http", "plugin", "wasm"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bevy_app = "0.15.0"
bevy_derive = "0.15.0"
bevy_hierarchy = "0.15.0"
bevy_ecs = { version = "0.15.0", features = ["multi_threaded"] }
bevy_tasks = "0.15.0"
bevy_app = "0.16.0"
bevy_derive = "0.16.0"
#bevy_hierarchy = "0.16.0"
bevy_ecs = { version = "0.16.0", features = ["multi_threaded"] }
bevy_tasks = "0.16.0"

crossbeam-channel = "0.5.11"
ehttp = { version = "0.5.0", features = ["native-async", "json"] }
@@ -27,7 +29,7 @@ serde_json = "1.0"
doctest = false

[dev-dependencies]
bevy = { version = "0.15.0", default-features = false, features = [
bevy = { version = "0.16.0", default-features = false, features = [
"animation",
"bevy_asset",
"bevy_gilrs",
@@ -40,6 +42,8 @@ bevy = { version = "0.15.0", default-features = false, features = [
"bevy_sprite",
"bevy_text",
"bevy_ui",
"bevy_window",
"bevy_log",
"multi_threaded",
"png",
"hdr",
23 changes: 17 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# bevy_http_client

[![CI](https://github.com/foxzool/bevy_http_client/workflows/CI/badge.svg)](https://github.com/foxzool/bevy_http_client/actions)
[![Crates.io](https://img.shields.io/crates/v/bevy_http_client)](https://crates.io/crates/bevy_http_client)
[![Downloads](https://img.shields.io/crates/d/bevy_http_client)](https://crates.io/crates/bevy_http_client)
[![Documentation](https://docs.rs/bevy_http_client/badge.svg)](https://docs.rs/bevy_http_client)
@@ -22,7 +23,7 @@ pub struct IpInfo {
fn main() {
let mut app = App::new();
app.add_plugins((MinimalPlugins, HttpClientPlugin))
.add_systems(Update, handle_response)
.add_systems(Update, (handle_response, handle_error))
.add_systems(
Update,
send_request.run_if(on_timer(std::time::Duration::from_secs(1))),
@@ -39,17 +40,27 @@ fn send_request(mut ev_request: EventWriter<TypedRequest<IpInfo>>) {
);
}

fn handle_response(mut ev_response: EventReader<TypedResponse<IpInfo>>) {
for response in ev_response.read() {
println!("ip: {}", response.ip);
/// consume TypedResponse<IpInfo> events
fn handle_response(mut events: ResMut<Events<TypedResponse<IpInfo>>>) {
for response in events.drain() {
let response: IpInfo = response.into_inner();
println!("ip info: {:?}", response);
}
}

fn handle_error(mut ev_error: EventReader<TypedResponseError<IpInfo>>) {
for error in ev_error.read() {
println!("Error retrieving IP: {}", error.err);
}
}

```

## Supported Versions

| bevy | bevy_http_client |
|------|------------------|
| 0.16 | 0.8 |
| 0.15 | 0.7 |
| 0.14 | 0.6 |
| 0.13 | 0.4, 0,5 |
@@ -63,7 +74,7 @@ Dual-licensed under either:
- [`MIT`](LICENSE-MIT): [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)
- [`Apache 2.0`](LICENSE-APACHE): [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)

at your option. This means that when using this crate in your game, you may choose which license to use.
At your option. This means that when using this crate in your game, you may choose which license to use.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as
defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
defined in the Apache-2.0 license, shall be dually licensed as above, without any additional terms or conditions.
2 changes: 1 addition & 1 deletion examples/ipinfo.rs
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ fn main() {

fn send_request(mut ev_request: EventWriter<HttpRequest>) {
let request = HttpClient::new().get("https://api.ipify.org").build();
ev_request.send(request);
ev_request.write(request);
}

fn handle_response(mut ev_resp: EventReader<HttpResponse>) {
47 changes: 47 additions & 0 deletions examples/observer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use bevy::{prelude::*, time::common_conditions::on_timer};

use bevy_http_client::prelude::*;

fn main() {
App::new()
.add_plugins((MinimalPlugins, HttpClientPlugin))
.add_systems(Startup, init_request)
.add_systems(
Update,
send_request.run_if(on_timer(std::time::Duration::from_secs(1))),
)
.run();
}

#[derive(Component)]
struct IpRequestMarker;

fn init_request(mut commands: Commands) {
let entity = commands.spawn(IpRequestMarker).id();
let request = HttpClient::new_with_entity(entity).get("https://api.ipify.org");
commands
.entity(entity)
.insert(request)
.observe(handle_response)
.observe(handle_error);
}

fn send_request(
clients: Query<&HttpClient, With<IpRequestMarker>>,
mut ev_request: EventWriter<HttpRequest>,
) {
let requests = clients
.iter()
.map(|c| c.clone().build())
.collect::<Vec<_>>();

ev_request.write_batch(requests);
}

fn handle_response(response: Trigger<HttpResponse>) {
println!("response: {:?}", response.text());
}

fn handle_error(error: Trigger<HttpResponseError>) {
println!("Error retrieving IP: {}", error.err);
}
8 changes: 1 addition & 7 deletions examples/typed.rs
Original file line number Diff line number Diff line change
@@ -20,19 +20,13 @@ fn main() {
}

fn send_request(mut ev_request: EventWriter<TypedRequest<IpInfo>>) {
ev_request.send(
ev_request.write(
HttpClient::new()
.get("https://api.ipify.org?format=json")
.with_type::<IpInfo>(),
);
}

// fn handle_response(mut ev_response: EventReader<TypedResponse<IpInfo>>) {
// for response in ev_response.read() {
// println!("ip: {}", response.ip);
// }
// }

/// consume TypedResponse<IpInfo> events
fn handle_response(mut events: ResMut<Events<TypedResponse<IpInfo>>>) {
for response in events.drain() {
20 changes: 14 additions & 6 deletions examples/window.rs
Original file line number Diff line number Diff line change
@@ -86,10 +86,15 @@ fn send_request(
mut status_query: Query<&mut Text, (With<ResponseText>, Without<ResponseIP>)>,
mut ip_query: Query<&mut Text, (With<ResponseIP>, Without<ResponseText>)>,
) {
status_query.single_mut().0 = "Requesting ".to_string();
ip_query.single_mut().0 = "".to_string();
if let Ok(mut text) = status_query.single_mut() {
text.0 = "Requesting ".to_string();
}
if let Ok(mut ip) = ip_query.single_mut() {
ip.0 = "".to_string();
}

let request = HttpClient::new().get("https://api.ipify.org").build();
ev_request.send(request);
ev_request.write(request);
}

fn handle_response(
@@ -98,9 +103,12 @@ fn handle_response(
mut ip_query: Query<&mut Text, (With<ResponseIP>, Without<ResponseText>)>,
) {
for response in ev_resp.read() {
let ip = response.text().unwrap_or_default();
ip_query.single_mut().0 = ip.to_string();
status_query.single_mut().0 = "Got ".to_string();
if let Ok(mut text) = status_query.single_mut() {
text.0 = "Got ".to_string();
}
if let Ok(mut ip) = ip_query.single_mut() {
ip.0 = response.text().unwrap_or_default().to_string();
}
}
}
fn handle_error(mut ev_error: EventReader<HttpResponseError>) {
66 changes: 55 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -3,9 +3,8 @@
use bevy_app::{App, Plugin, Update};
use bevy_derive::Deref;
use bevy_ecs::{prelude::*, world::CommandQueue};
use bevy_hierarchy::DespawnRecursiveExt;
use bevy_tasks::IoTaskPool;
use crossbeam_channel::Receiver;
use crossbeam_channel::{Receiver, Sender};
use ehttp::{Headers, Request, Response};

use crate::prelude::TypedRequest;
@@ -131,6 +130,27 @@ impl HttpClient {
Self::default()
}

/// his method is used to create a new `HttpClient` instance with `Entity`.
///
/// # Arguments
///
/// * `entity`: Target Entity
///
/// returns: HttpClient
///
/// # Examples
///
/// ```
/// let e = commands.spawn().id();
/// let http_client = HttpClient::new_with_entity(e)
/// ```
pub fn new_with_entity(entity: Entity) -> Self {
Self {
from_entity: Some(entity),
..Default::default()
}
}

/// This method is used to create a `GET` HTTP request.
///
/// # Arguments
@@ -490,12 +510,16 @@ impl HttpResponseError {

/// task for ehttp response result
#[derive(Component, Debug)]
pub struct RequestTask(pub Receiver<CommandQueue>);
pub struct RequestTask {
tx: Sender<CommandQueue>,
rx: Receiver<CommandQueue>,
}

fn handle_request(
mut commands: Commands,
mut req_res: ResMut<HttpClientSetting>,
mut requests: EventReader<HttpRequest>,
q_tasks: Query<&RequestTask>,
) {
let thread_pool = IoTaskPool::get();
for request in requests.read() {
@@ -506,7 +530,8 @@ fn handle_request(
} else {
(commands.spawn_empty().id(), false)
};
let (tx, rx) = crossbeam_channel::bounded(1);

let tx = get_channel(&mut commands, q_tasks, entity);

thread_pool
.spawn(async move {
@@ -519,40 +544,59 @@ fn handle_request(
world
.get_resource_mut::<Events<HttpResponse>>()
.unwrap()
.send(HttpResponse(res));
.send(HttpResponse(res.clone()));
world.trigger_targets(HttpResponse(res), entity);
}
Err(e) => {
world
.get_resource_mut::<Events<HttpResponseError>>()
.unwrap()
.send(HttpResponseError::new(e.to_string()));
world
.trigger_targets(HttpResponseError::new(e.to_string()), entity);
}
}

if has_from_entity {
world.entity_mut(entity).remove::<RequestTask>();
} else {
world.entity_mut(entity).despawn_recursive();
if !has_from_entity {
world.entity_mut(entity).despawn();
}
});

tx.send(command_queue).unwrap();
})
.detach();

commands.entity(entity).insert(RequestTask(rx));
req_res.current_clients += 1;
}
}
}

fn get_channel(
commands: &mut Commands,
q_tasks: Query<&RequestTask>,
entity: Entity,
) -> Sender<CommandQueue> {
if let Ok(task) = q_tasks.get(entity) {
task.tx.clone()
} else {
let (tx, rx) = crossbeam_channel::bounded(5);

commands.entity(entity).insert(RequestTask {
tx: tx.clone(),
rx: rx.clone(),
});

tx
}
}

fn handle_tasks(
mut commands: Commands,
mut req_res: ResMut<HttpClientSetting>,
mut request_tasks: Query<&RequestTask>,
) {
for task in request_tasks.iter_mut() {
if let Ok(mut command_queue) = task.0.try_recv() {
if let Ok(mut command_queue) = task.rx.try_recv() {
commands.append(&mut command_queue);
req_res.current_clients -= 1;
}
2 changes: 1 addition & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub use super::{
typed::{HttpTypedRequestTrait, TypedRequest, TypedResponse, TypedResponseError},
HttpClient, HttpClientPlugin, HttpClientSetting, HttpRequest, HttpResponse, HttpResponseError,
RequestTask,
typed::{HttpTypedRequestTrait, TypedRequest, TypedResponse, TypedResponseError},
};
Loading