Giter VIP home page Giter VIP logo

actix-extras's Introduction

actix-extras

A collection of additional crates supporting Actix Web.

CI codecov Chat on Discord Dependency Status

Crates by @actix

Crate
actix-cors crates.io dependency status Cross-Origin Resource Sharing (CORS) controls.
actix-identity crates.io dependency status Identity management.
actix-limitation crates.io dependency status Rate-limiting using a fixed window counter for arbitrary keys, backed by Redis.
actix-protobuf crates.io dependency status Protobuf payload extractor.
actix-session crates.io dependency status Session management.
actix-settings crates.io dependency status Easily manage Actix Web's settings from a TOML file and environment variables.
actix-web-httpauth crates.io dependency status HTTP authentication schemes.
actix-ws crates.io dependency status WebSockets for Actix Web, without actors.

Community Crates

These crates are provided by the community.

Crate
actix-web-lab crates.io dependency status Experimental extractors, middleware, and other extras for possible inclusion in Actix Web.
actix-multipart-extract crates.io dependency status Better multipart form support for Actix Web.
actix-form-data crates.io dependency status Multipart form data from actix multipart streams
actix-governor crates.io dependency status Rate-limiting backed by governor.
actix-casbin crates.io dependency status Authorization library that supports access control models like ACL, RBAC & ABAC.
actix-ip-filter crates.io dependency status IP address filter. Supports glob patterns.
actix-web-static-files crates.io dependency status Static files as embedded resources.
actix-web-grants crates.io dependency status Extension for validating user authorities.
aliri_actix crates.io dependency status Endpoint authorization and authentication using scoped OAuth2 JWT tokens.
actix-web-flash-messages crates.io dependency status Support for flash messages/one-time notifications in actix-web.
awmp crates.io dependency status An easy to use wrapper around multipart fields for Actix Web.
tracing-actix-web crates.io dependency status A middleware to collect telemetry data from applications built on top of the Actix Web framework.
actix-hash crates.io dependency status Hashing utilities for Actix Web.
actix-bincode crates.io dependency status Bincode payload extractor for Actix Web
sentinel-actix crates.io dependency status General and flexible protection for Actix Web
actix-telepathy crates.io dependency status Build distributed applications with RemoteActors and RemoteMessages.
apistos crates.io dependency status Automatic OpenAPI v3 documentation for Actix Web

To add a crate to this list, submit a pull request.

actix-extras's People

Contributors

aaron1011 avatar adwhit avatar ava57r avatar dependabot[bot] avatar doumanash avatar dowwie avatar fafhrd91 avatar fuchsnj avatar gowee avatar hstefan avatar jeizsm avatar jesskfullwood avatar johntitor avatar jrconlin avatar killercup avatar kornelski avatar krircc avatar lukemathwalker avatar memoryruins avatar messense avatar mitsuhiko avatar mockersf avatar neopallium avatar niklasf avatar radix avatar robjtede avatar svartalf avatar svenstaro avatar tazjin avatar turbo87 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

actix-extras's Issues

Mismatch between Request and Response headers

This crate has some default behaviour that allows for the client to specify headers in Access-Control-Request-Headers that it wants to be able to access on the response.

This is not the correct intention of this header, but worse it actually breaks things if you try to add explicit headers using .allowed_header().

Access-Control-Request-Headers is meant "to let the server know which HTTP headers the client might send when the actual request is made". It is not intended for the client to indicate which headers it wants to access in the response.

If I have my CORS setup as:

                Cors::new()
                    .allowed_header(header::ETAG)
                    .finish(),

Then an incoming request with:

Access-Control-Request-Headers: authorization

Will fail because authorization is not in the "allowed_header" list. Instead I've got to configure CORS as:

                Cors::new()
                    .allowed_header(header::ETAG)
                    .allowed_header(header::AUTHORIZATION)
                    .finish(),

Even though Authorization will never be sent in a response.

Your Environment

-> % rustc -V
rustc 1.45.2 (d3fb005a3 2020-07-31)
-> % cat crates/server/Cargo.toml | grep actix
actix-cors = "0.2.0"
actix-http = "1.0.1"
actix-web = "2.0.0"

Fix long lasting auto-prolonged session

original PR #1292

  1. auto prolonging is based only on expires_in. It should consider also max_age parameter - someone can set only max_age and prolonging will not work.
  2. expires_in should support setting value also as datetime, not only as seconds - internally is converted to datetime and cookie parameter expires is datetime value, not seconds as max_age

How to get session in the next middleware?

First, I defined a actix-session middleware.
Then, I added another โ€˜CheckLoginโ€™ middleware.

let private_key = rand::thread_rng().gen::<[u8; 32]>();
App::new()
            .data(tera)
            .wrap(middleware::Logger::default())
            .wrap(CookieSession::signed(&private_key).name("session").secure(false))
            .wrap(admin::CheckLogin) 
            .service(index)
            .service(login)

However, I cannot get the session in โ€˜CheckLoginโ€™ .like this:

fn call(&mut self, req: ServiceRequest) -> Self::Future {
        if req.path().len() > 8 && &req.path()[0..8] == "/static/" {
            Either::Left(self.service.call(req))
        } else {
            let is_logged_in = false;
            let (r, pl) = req.into_parts();
            let session:Session = r.get_session();
            if let Ok(v) = session.get::<usize>("counter") { 
                if let Some(count) = v { 
                    if count > 0 { 
                        println!("CheckLogin SESSION value: {}", count);
                    }
                }
            }
            let req = ServiceRequest::from_parts(r, pl).ok().unwrap();
            if is_logged_in || req.path() == "/login" {
                Either::Left(self.service.call(req))
            } else {
                Either::Right(ok(req.into_response(
                    HttpResponse::Found()
                        .header(http::header::LOCATION, "/login")
                        .finish()
                        .into_body(),
                )))
            }
        }
    }

Cookie HTTP Only error

I get an error trying to set cookie_http_only(true). I'm not sure what I'm doing wrong.

error[E0599]: no method named `cookie_http_only` found for struct `actix_redis::session::RedisSession` in the current scope
    --> src/main.rs:1103:22
     |
1103 |                     .cookie_http_only(true)
     |                      ^^^^^^^^^^^^^^^^ method not found in `actix_redis::session::RedisSession`

unable to set redis value

Can't set new value with redis actor

    let a = RedisActor::start("127.0.0.1:6379");
    a.send(Command(resp_array!["SET", "aaa", "bbbb"]));

ะธะทะพะฑั€ะฐะถะตะฝะธะต
and no new values

tried with actix-redis = "0.9.0-alpha.2" and alpha 1

CORS: allowed_origin support vec of origins ?

If origins are configured somewhere, how to build Cors with a vec of allowed_origins, something like this?

let cors = Cors::default().allowed_origins(vec![origin1, origin2, origin3];

Cors::default() works but Cors::build() doesn't

Hello, for history reason, I'm still using [email protected], there are too much work to do for upgrading so I didn't do it yet.

While using Cors middleware I found that Cors::default works fine but Cors::build doesn't work with OPTIONS request.

My example code:

This doesn't work

app.middleware(
 Cors::build()
        .allowed_methods(
            CONFIG
                .cors
                .access_control_allow_methods
                .iter()
                .map(|x| &**x)
                .collect::<Vec<&str>>(),
        )
        .allowed_headers(
            CONFIG
                .cors
                .access_control_allow_headers
                .iter()
                .map(|x| &**x)
                .collect::<Vec<&str>>(),
        )
        .supports_credentials()
        .max_age(CONFIG.cors.access_control_max_age)
        .finish())
        .scope(....)

But this works:

app.middleware(Cors::default()).scope(.....)

Support for JWT handling

Hi ! First of all, thank you for your amazing work !
I'm planning on adding support for JWT to the actix-web-httpauth crate.
Is this the right place to implement such feature ? Or would it be in another crate ?

Like for the Bearer auth already implemented, the JWT auth would have a config with different settings on how to validate the JWT and a struct wrapped in an Arc<RwLock<>> in which to store, access and hot-replace the JWKS.

An extractor would also be available to extract common header fields as well as common claims. (Maybe find a way to make the claims struct dynamic, so that people could plug-in there own struct for the claims)

This features would require the following crates :

  • jsonwebtoken
  • serde
  • serde_json
  • chrono

tracking cors 1.0 promotion

Should be pretty easy to get actix-cors in a 1.0 state since it's feature complete.

  • panic on wildcard origin #114
  • clean up docs about when panic occurs
  • consider removing CorsFactory #119
  • address any other open issues
  • is disable_preflight needed?
    • im sure someone out there has a use case
    • could consider adding a deprecation notice in v1 asking anyone with a use case can open an issue
  • is send_wildcard needed?
    • we'll leave it but it's not very useful in today's web world
  • allowed_origin_fn without allowed_origin bug fixed in #119
  • pass origin header down as parameter to allow origin fns (+ optimise origin extraction) [#120]
  • should CorsError be public?
    • there is probably a use case somewhere for wanting to manually return these error, in which case having the pre-built ErrorResponse impls could be useful.

Firefox issue with session and static files

I found some strange issue with Firefox (76.0.1) in my project.

Cargo.toml

[package]
name = "actix-session-test"
version = "0.1.0"
authors = [""]
edition = "2018"

[dependencies]
actix-files = "0.2.1"
actix-web = "2.0.0"
actix-rt = "1.1.1"
actix-service = "1.0.5"
actix-session = "0.3.0"

I created a minimal example for this issue with steps to reproduce https://github.com/errmac-v/actix-issue.
In general, when I try to open a static file (I use actix-files) and then reload this page, session is purging. It happens if I use req.get_session() in middleware.
Is it related to actix-web or actix-extras or it's a Firefox issue? It works well on Chrome, btw.

Custom error response

Is there any way to catch and transform the authentication errors that are generated by the middleware before they get sent as a response?

If not do you think this would be best implemented by adding a error_handler to the middleware initialisation, or maybe having an alternative signature for the validator function that takes a cred: Result<BasicAuth, Error> ?

actix_cors doesn't send CORS headers other middleware errors

Expected Behavior

Keep setting cors response headers, even if other middleware has errors.

Current Behavior

If an error occurs in the middleware chain, actix_cors will return this error directly, and doesn't setting any response headers.

Your Environment

  • Rust Version (I.e, output of rustc -V):
  • Actix Web Version: 2.0.0
  • Actix Cors Version: 0.2.0

actix-redis docs looks outdated

Hi!
Thanks for all the awesome work on actix!

At the moment Im working on an Actix/Redis implementation but I found issues using the crate actix_redis.

The current docs point out references to App.middleware and actix-web v2 implements wrap instead. (Correct me if Im wrong).

This is my current implementation:

#[macro_use]
extern crate log;

#[macro_use]
extern crate diesel;

#[macro_use]
extern crate diesel_migrations;

use actix_web::middleware::Logger;
use actix_web::{App, HttpServer};
use actix_redis::{RedisSession};
use dotenv::dotenv;
use std::env;

mod schema;
mod server;
mod user;
mod auth;

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
	dotenv().ok();
	env_logger::init();

	// Initialize Database
	server::init_database();

	let host = env::var("HOST").expect("Host not set");
	let port = env::var("PORT").expect("Port not set");
	let redis_host = env::var("REDIS_HOST").expect("Redis Host is missing");
	let redis_port = env::var("REDIS_PORT").expect("Redis Port is missing");

	let server = HttpServer::new(move ||
		App::new()
			.wrap(Logger::default())
			.wrap(RedisSession::new(format!("{}:{}", redis_host, redis_port), &[0; 32]))
			.configure(user::init_routes)
			.configure(auth::init_routes)
	);

	server.bind(format!("{}:{}", host, port))?
		.run()
		.await
}

And Im getting multiple messages from the logger, like an infinity loop:

[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
^Cactix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_redis::redis] Connected to redis server: 127.0.0.1:6379
[2020-03-08T23:56:27Z INFO  actix_server::builder] SIGINT received, exiting
[2020-03-08T23:56:27Z ERROR actix_redis::redis] Can not connect to redis server: Mailbox has closed
[2020-03-08T23:56:27Z ERROR actix_redis::redis] Can not connect to redis server: Mailbox has closed

Any help on this?

Thanks in advance!

actix-redis uses only u16 as TTL

I am not able to set TTL of actix-redis session to more than 65535 seconds (about 18 hours) bcs it uses just u16 variable:
pub fn ttl(self, ttl: u16) -> Self

Conflict between HttpAuthentication::bearer and actix-cors

Expected Behavior

Be able to use HttpAuthentication::bearer and actix-cors in the same project

Current Behavior

Hi, I am trying to use HttpAuthentication::bearer in a project that also uses actix-cors, if I use HttpAuthentication::bearer or actix-cors alone it works fine, but if I use both I get an error saying that cors has block the request due to No 'Access-Control-Allow-Origin' header is present on the requested resource.

Steps to Reproduce (for bugs)

My code is:

#[actix_rt::main]
pub async fn init() -> std::io::Result<()> {
 let port = env::var("PORT").unwrap_or_else(|_e| "8000".to_string());
 let mut socket = "127.0.0.1".to_string();
 socket.push(':');
 socket = socket + &port;
 let db_state = db_mongodb::DB::init().await;

 HttpServer::new(move || {
    App::new()
        .wrap(
            Cors::permissive()
        )
        .data(db_state.clone())
        .service(
            web::scope("/api")
            .wrap(HttpAuthentication::bearer(auth::validator))
            .configure(routes::init_secured)
        )
        .service(
            web::scope("/public")
            .configure(routes::init_public)
        )
 })
 .bind(socket).unwrap()
 .run()
 .await
}

Your Environment

  • Rust Version: rustc 1.47.0 (18bf6b4f0 2020-10-07)
  • actix-web = "3.2.0"
  • actix-rt = "1.1.1"
  • actix-web-httpauth = "0.5.0"
  • actix-cors = "0.5.1"
  • Operating System: Debian GNU/Linux 10 (buster)
  • Kernel: Linux 4.19.0-12-amd64
  • Architecture: x86-64

Session: time to live

Extend Session api to getting time until a key in the session will expire. Similar to Redis command ttl.

Extend Session api to reset ttl back to the initial time. For sessions with Redis, the expire command could be used.

actix-cors v0.5.4 not support actix-web v4.0.0-beta.1 version , but in actix-web v3.3.2 is fine

Current Behavior

code :

use actix_cors::Cors;
use actix_web::{get, http, web, App, HttpRequest, HttpResponse, HttpServer};

#[get("/index.html")]
async fn index(req: HttpRequest) -> &'static str {
    "<p>Hello World!</p>"
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        let cors = Cors::default()
              .allowed_origin("https://www.rust-lang.org/")
              .allowed_origin_fn(|origin, _req_head| {
                  origin.as_bytes().ends_with(b".rust-lang.org")
              })
              .allowed_methods(vec!["GET", "POST"])
              .allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
              .allowed_header(http::header::CONTENT_TYPE)
              .max_age(3600);

        App::new()
            .wrap(cors)
            .service(index)
    })
    .bind(("127.0.0.1", 8082))?
    .run()
    .await;

    Ok(())
}

cargo run :

warning: unused imports: `HttpResponse`, `web`
 --> src/main.rs:2:28
  |
2 | use actix_web::{get, http, web, App, HttpRequest, HttpResponse, HttpServer};
  |                            ^^^                    ^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0277]: the trait bound `Cors: Transform<actix_web::app_service::AppRouting, ServiceRequest>` is not satisfied
  --> src/main.rs:23:19
   |
23 |             .wrap(cors)
   |                   ^^^^ the trait `Transform<actix_web::app_service::AppRouting, ServiceRequest>` is not implemented for `Cors`

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0277`.
error: could not compile `test_cors`

Your Environment

  • rustc -V
    rustc 1.49.0 (e1884a8e3 2020-12-29)

  • Actix-* crate(s) Version:

[dependencies]
actix-web = { version = "4.0.0-beta.1", features = ["openssl"] }
toml = "0.5.8"
actix-service = "2.0.0-beta.3"
actix-cors = "0.5.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
json = "0.12.4"

[actix-redis]ERR unknown command 'GET' be raised when access with Firefox/77.0b9, possibly caused by lacking of HttpOnly field in Cookie

I wrote an minimum test scenario in which we can reproduce the problem.

Expected Behavior

In my scenario, we should get 'It works!' in FireFox/77.0b9 or in BurpSuite repeaters.

Current Behavior

I got a 500 Internal Error only told me ERR unknown command 'GET'

Possible Solution

Still trying to debugging, but I'm not familiar with actix-redis.

Steps to Reproduce (for bugs)

1.Dependencies as following

[dependencies]
actix-redis = "0.8.2"
actix-rt = "1.1.1"
actix-session = "0.3.0"
actix-web = "2.0.0"
  1. Code which can reproduce the case as following
use actix_redis::RedisSession;
use actix_rt;
use actix_session::Session;
use actix_web::get;
use actix_web::http::header;
use actix_web::App;
use actix_web::HttpResponse;
use actix_web::HttpServer;

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(move || App::new().wrap(init_redis()).service(a).service(b))
        .bind("127.0.0.1:8888")?
        .run()
        .await
}

fn init_redis() -> RedisSession {
    RedisSession::new("localhost:6379", &[0; 56])
}

#[get("/a")]
async fn a(_session: Session) -> HttpResponse {
    HttpResponse::SeeOther()
        .header(header::LOCATION, "b")
        .finish()
}

#[get("/b")]
async fn b() -> &'static str {
    "It works!"
}
  1. Access http://localhost:8888/a with firefox 77.0 developer beta 9, or send the request to 127.0.0.1:8888 with following bash script, we will be able to reproduce the issue.
cat << EOF | nc 127.0.0.1 8888
GET /b HTTP/1.1
Host: localhost:8888
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cookie: actix-session=qg0BtRsNKkT1KLggoym0OYSZxO59iu4XgCkDPcNjEFc=h6A5pSZGzl2PRmfmlZbrkXMufpyfisav
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache

EOF
HTTP/1.1 500 Internal Server Error
content-length: 25
connection: close
content-type: text/plain; charset=utf-8
date: Mon, 01 Jun 2020 15:36:40 GMT

ERR unknown command 'GET'
  1. Append ; HttpOnly to the end of Cookie header, that is execute the following bash script, we can get the expected beheaviour.
cat << EOF | nc 127.0.0.1 8888
GET /b HTTP/1.1
Host: localhost:8888
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cookie: actix-session=qg0BtRsNKkT1KLggoym0OYSZxO59iu4XgCkDPcNjEFc=h6A5pSZGzl2PRmfmlZbrkXMufpyfisav; HttpOnly
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache

EOF
HTTP/1.1 200 OK
content-length: 9
connection: close
content-type: text/plain; charset=utf-8
date: Mon, 01 Jun 2020 15:42:08 GMT

Context

Well, I'm afraid this will affect guests who access my site with firefox.

Your Environment

  • Rust Version (I.e, output of rustc -V): rustc 1.43.1 (8d69840ab 2020-05-04)
  • Actix-* crate(s) Version:
[dependencies]
actix-redis = "0.8.2"
actix-rt = "1.1.1"
actix-session = "0.3.0"
actix-web = "2.0.0"

Document using protobuf from the client

Expected Behavior

There is no documentation about constructing protobuf messages to issue HTTP requests from the client only HTTPResponses are covered.

Current Behavior

The documentation and example only cover server side and doesn't cover client.

Possible Solution

Add more documentation and maybe example app.

Steps to Reproduce (for bugs)

N/A

Context

I am trying to implement an app which acts both as http client and server and therefore need to be able to construct protobuf messages and include them in both HTTResponse and HTTRequest.

Your Environment

  • Rust Version (I.e, output of rustc -V): 1.43.1
  • Actix-* crate(s) Version:
    • actix: 0.9.0
    • actix-protobuf: 0.5.1

CORS Issue when requesting backend apis

Hello, I have an issue with CORS.
I had added CORS config in my server :
https://github.com/helabenkhalfallah/rust-rest-api/blob/master/src/main.rs#L59

Expected Behavior

Frontend request can get data from my backend.

Current Behavior

I have this issue when calling requests from frontend :

Access to fetch at 'http://localhost:4000/get-all-users' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

https://github.com/helabenkhalfallah/rust-react-wasm-js/blob/master/src/lib.rs#L116

Steps to Reproduce (for bugs)

  1. launch backend
  2. launch frontend
  3. each frontend request fails.

Context

Consuming backend APIs from my frontend.

Your Environment

  • Rust Version (I.e, output of rustc -V): rustc 1.44.1
  • Actix Web Version: 2

Have I missed a config ?

Thank you so much for your help :) :)

actix-redis depends on old version of package(s)

dependencies should be upgraded. I have problem with package "time". Current version is 0.2.9, but actix-redis depends on 0.1.42, which is not compatible:
I want set .cookie_max_age(Duration::days(1))

[httpauth] Optional credentials

Expected Behavior

Set Authorization header optional.

Current Behavior

If I donโ€™t send the Authorization header, the extractor fail and returns a 401 error.

Possible Solution

Impl AuthExtrator for Option<BasicAuth> and Option<BearerAuth>.

Context

Some routes arenโ€™t require authentication, typically route for registration/sign in.

Your Environment

  • Rust Version (I.e, output of rustc -V): rustc 1.48.0 (7eac88abb 2020-11-16)
  • actix-web-httpauth crate Version: 0.5.0

Allow Access-Control-Allow-Origin in Actix-CORS

I have Rust code running on api.myexample.com. Now I want that codes from other domains can make GET/POST request to api.myexample.com.

Now this gives the following error:


[Error] Origin http://othersitecallingtheapi.com is not allowed by Access-Control-Allow-Origin

I should be able to fix this somehow by configuring the CORS. But I don't see anywhere in the Actix-CORS documentation on how to allow Access-Control-Allow-Origin.

Thanks!

[actix-redis] doesn't run at all

   Compiling actix-redis v0.9.0-alpha.2
error[E0277]: the trait bound `redis_async::resp::RespCodec: tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not satisfied
  --> /home/venny/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-redis-0.9.0-alpha.2/src/redis.rs:30:5
   |
30 |     cell: Option<actix::io::FramedWrite<RespValue, WriteHalf<TcpStream>, RespCodec>>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not implemented for `redis_async::resp::RespCodec`
   |
   = note: required by `actix::io::FramedWrite`

error[E0277]: the trait bound `redis_async::resp::RespCodec: tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not satisfied in `redis::RedisActor`
  --> /home/venny/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-redis-0.9.0-alpha.2/src/redis.rs:51:6
   |
51 | impl Actor for RedisActor {
   |      ^^^^^ within `redis::RedisActor`, the trait `tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not implemented for `redis_async::resp::RespCodec`
   |
   = note: required because it appears within the type `actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>`
   = note: required because it appears within the type `std::option::Option<actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>>`
   = note: required because it appears within the type `redis::RedisActor`

error[E0277]: the trait bound `redis_async::resp::RespCodec: tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not satisfied in `redis::RedisActor`
  --> /home/venny/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-redis-0.9.0-alpha.2/src/redis.rs:96:6
   |
96 | impl Supervised for RedisActor {
   |      ^^^^^^^^^^ within `redis::RedisActor`, the trait `tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not implemented for `redis_async::resp::RespCodec`
   |
   = note: required because it appears within the type `actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>`
   = note: required because it appears within the type `std::option::Option<actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>>`
   = note: required because it appears within the type `redis::RedisActor`

error[E0277]: the trait bound `redis_async::resp::RespCodec: tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not satisfied in `redis::RedisActor`
   --> /home/venny/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-redis-0.9.0-alpha.2/src/redis.rs:105:6
    |
105 | impl actix::io::WriteHandler<io::Error> for RedisActor {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `redis::RedisActor`, the trait `tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not implemented for `redis_async::resp::RespCodec`
    |
    = note: required because it appears within the type `actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>`
    = note: required because it appears within the type `std::option::Option<actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>>`
    = note: required because it appears within the type `redis::RedisActor`

error[E0277]: the trait bound `redis_async::resp::RespCodec: tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not satisfied in `redis::RedisActor`
   --> /home/venny/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-redis-0.9.0-alpha.2/src/redis.rs:112:6
    |
112 | impl StreamHandler<Result<RespValue, RespError>> for RedisActor {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `redis::RedisActor`, the trait `tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not implemented for `redis_async::resp::RespCodec`
    |
    = note: required because it appears within the type `actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>`
    = note: required because it appears within the type `std::option::Option<actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>>`
    = note: required because it appears within the type `redis::RedisActor`

error[E0277]: the trait bound `redis_async::resp::RespCodec: tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not satisfied in `redis::RedisActor`
   --> /home/venny/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-redis-0.9.0-alpha.2/src/redis.rs:130:6
    |
130 | impl Handler<Command> for RedisActor {
    |      ^^^^^^^^^^^^^^^^ within `redis::RedisActor`, the trait `tokio_util::codec::encoder::Encoder<redis_async::resp::RespValue>` is not implemented for `redis_async::resp::RespCodec`
    |
    = note: required because it appears within the type `actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>`
    = note: required because it appears within the type `std::option::Option<actix::io::FramedWrite<redis_async::resp::RespValue, tokio::io::split::WriteHalf<tokio::net::tcp::stream::TcpStream>, redis_async::resp::RespCodec>>`
    = note: required because it appears within the type `redis::RedisActor`

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0277`.
error: could not compile `actix-redis`.

AuthenticationMiddleware was called already panic

We are observing that our actix-web application occasionally panics under a lot of contention with the message "AuthenticationMiddleware was called already". This seems to come from here https://github.com/actix/actix-web-httpauth/blob/v0.4.0/src/middleware.rs#L184

We have recently migrated to actix-web 2.0 and actix-web-httpauth 0.4. We haven't observed this before the migration.

As this doesn't happen for all requests, there seems to be some race condition either within actix-web or actix-web-httpauth that causes this.

We use bearer token authorization and within the validation function, to validate the token, we just perform an HTTP request with reqwest and depending on the result return Ok or Err.

Example for actix_web::client

@tilpner suggested that it would be nice to have an example of the actix_web::client and Authorization header combination.

This issue is hereby a tracking issue for this example.

HttpAuthentication middleware doesn't behave properly on tests

Expected Behavior

When using a custom HttpAuthentication middleware with a process_fn looking like this:

pub async fn bearer_token_middleware(mut req: ServiceRequest, credentials: BearerAuth) -> Result<ServiceRequest, Error> {
    let session = match
        Session::find_by("token", credentials.token(), &req.app_data().unwrap()).await
        {
            Ok(record) => record,
            Err(_error) => return Err(MyErrors::Unauthorized))
        };
    req.headers_mut().insert(http::HeaderName::from_static(USER_ID), session.record.user_id.parse()?);
    Ok(req)
}

that simply checks the bearer token and stores a new header value containing the associated user id, it should work. And it does at runtime, however when testing (actix tests) it should behave the same

the following extract from a test I wrote:

let mut app = tokio_test::block_on(test::init_service(
                App::new()
                    .data(dbPool.clone())
                    .configure(config::web_service::config_routes)
            ));
let token = String::from("Wrong bearer');
let req = test::TestRequest::get()
                .uri(&format!("/api/users/{}", &user_id))
                .header(http::header::AUTHORIZATION, token)
                .to_request();
let resp = tokio_test::block_on(test::call_service(&mut app, req));
assert!(!resp.status().is_success());

this test should succeed but instead it fails because test::call_service panics on error (unwrap). The middleware doesn't seem to build a response when working with tests, and instead returns a Result<ServiceResponse, Error>

CLI result: $TEST panicked at 'called `Result::unwrap()` on an `Err` value: Unauthorized' the panic is not from my code but from the actix-web::test::call_service function at github.com-1ecc6299db9ec823/actix-web-2.0.0/src/test.rs:123:5

I am on the last versions of all actix crates.

thanks for your help

actix-protobuf does not support 3.0.0-alpha.3

Expected Behavior

Current Behavior

Possible Solution

Steps to Reproduce (for bugs)

  1. when call protobuf() method
HttpResponse::Ok().protobuf(msg)
  1. compile error
no method named `protobuf` found for struct `actix_http::response::ResponseBuilder` in the current scope
method not found in `actix_http::response::ResponseBuilder`

Context

Your Environment

  • Rust Version (I.e, output of rustc -V): rustc 1.43.0-nightly (5d04ce67f 2020-02-13)
  • Actix-* crate(s) Version:
    actix-web = "3.0.0-alpha.3"
    actix-protobuf = "0.5"

migration plan

identity & session currently have dependencies on a release with the time crate changes from -web

TODO:

  • create repo readme
  • merge crates into workspace (almost)
  • set up CI
  • ask about an actix-web v3 alpha to hook up session & identity to
  • re-point repository metadata items to this repo
  • archive redis, protobuf & httpauth repos and update readmes
  • delete cors, identity & session crates from -web

MIGRATION:

  • actix-cors
  • actix-identity
  • actix-redis
  • actix-protobuf
  • actix-web-httpauth
  • actix-session

Help using Actix Redis Session with Heroku-Redis

I can't seem to connect to it. I keep getting this error printed every second.

2020-03-05T14:36:50.954618+00:00 app[web.1]: [2020-03-05T14:36:50Z ERROR actix_redis::redis] Can not connect to redis server: Failed resolving hostname: no record found for name: redis type: AAAA class: IN

The setup guide in Heroku documentation only says you need to grab the REDIS_URL from env variable and you are good to go.

Here's how I set it up,

let redis_url = env::var("REDIS_URL").expect("REDIS_URL env variable cannot be found.");
    db::init();
    let mut listenfd = ListenFd::from_env();
    let mut server = HttpServer::new(move || {
        App::new()
            .wrap(RedisSession::new(format!("{}", redis_url), &[0; 32]))
            .service(index)
            .configure(user::init_routes)
            .configure(auth::init_routes)
            .configure(organ::init_routes)
    });

Where, REDIS_URL is something like ...

REDIS_URL: redis://h:skdhjgkldfshgkldfhlgfdg23affde@ac-23-3232-3.compute-1.amazonaws.com:12345

I assume the stuff after : is the port? Nonetheless, I can't find more information about this. Or where to look.

How to get all the data from a session store?

Is there an api to get all the key-value pairs stored in a session store?

I haven't found how to do it using the actix-session api:

Looking at the api, the value and keys are stored as strings in the SessionInner HashMap and it could be possible to provide a method to get access to this store.

If this is not currently possible, I would be happy to implement an api to expose this. I would need some guidance on the desired api signature because there could be several approaches.

unresolved import derive_more::Error

Expected Behavior

When trying to use actix-cors 0.5.2 with Actix-web 3.2.0, i experience this error

Current Behavior

Compiling actix-cors v0.5.2
error[E0432]: unresolved import `derive_more::Error`
 --> C:\Users\Arley\.cargo\registry\src\github.com-1ecc6299db9ec823\actix-cors-0.5.2\src\error.rs:3:28
  |
3 | use derive_more::{Display, Error};
  |                            ^^^^^ no `Error` in the root

error: cannot determine resolution for the derive macro `Error`
 --> C:\Users\Arley\.cargo\registry\src\github.com-1ecc6299db9ec823\actix-cors-0.5.2\src\error.rs:6:33
  |
6 | #[derive(Debug, Clone, Display, Error)]
  |                                 ^^^^^
  |
  = note: import resolution is stuck, try simplifying macro imports

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0432`.
error: could not compile `actix-cors`

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed

Process finished with exit code 101

Steps to Reproduce (for bugs)

  1. Cargo.toml
  2. cargo run

Your Environment

nightly-x86_64-pc-windows-gnu
rustc 1.49.0-nightly (1773f60ea 2020-11-08)

Unsucsesful Authentication returns 500, not 401/403

Expected Behavior

response should return 401/403 resonse

Current Behavior

500 is being thrown

Steps to Reproduce (for bugs)

// from example
async fn validator(
    req: ServiceRequest,
    _credentials: BasicAuth,
) -> Result<ServiceRequest, Error> {
    Err(Error::from("bad credentials"))
}

Context

Isnt the whole point of authentocation middleware to return 401/403 on failed authentication?
Instead it seem to propagate error, and result in 500

Your Environment

  • Rust Version rustc 1.48.0 (7eac88abb 2020-11-16)
  • Actix-* actix-web = "3"

Could not compile actix-redis 0.9.0-alpha.1

When I try to build empty project with cargo new, I get an error wrong number of type arguments: expected 3, found 2. Is there an example with stable versions (it doesn't work for actix-redis 0.8 as well)? Or it can be fixed for alpha?

src/redis.rs:30:18

cell: Option<actix::io::FramedWrite<WriteHalf<TcpStream>, RespCodec>>,

Cargo.toml

[package]
name = "actix-redis-test"
version = "0.1.0"
authors = [""]
edition = "2018"

[dependencies]
actix-redis = "0.9.0-alpha.1"
actix-web = "3.0.0-alpha.2"

session.purge() doesn't do anything and documentation for clear(), purge(), renew()

I'm using actix-session with the default CookieSession backend. I'm trying to figure out how to delete a cookie from the user's browser.

session.purge() doesn't change anything about the cookie, and since there's no way to get to the SessionStatus enum (it's private), when you then load that session in a different handler, even though it was purged, the new handler thinks the session cookie is still valid.

I can run session.clear() followed by session.renew() and it wipes out the values, but I can't seem to figure out the point of purge().

If there's an easy way to delete the cookie, I think the docs ought to be updated as well.

I think the docs ought to be updated anyway as well with examples showing when to use clear() versus purge(), when you explicitly need to call renew().

I also think calling purge should alter the session cookies expiration time to some day in the past so that the cookie drops from the browser session altogether as well.

Strange `actix_identity::Identity` behavour when used with `configure`.

Hi. I slightly changed this example and got unexpected behavior. I added configure part after wrap with same three urls under scope cfg. Here is how it looks:

// main.rs
use actix_web::{web, App, HttpResponse, HttpServer};
use actix_identity::{Identity, CookieIdentityPolicy, IdentityService};

use rand::Rng;


async fn index(id: Identity) -> String {
    format!(
        "Hello {}",
        id.identity().unwrap_or_else(|| "Anonymous".to_owned())
    )
}

async fn login(id: Identity) -> HttpResponse {
    id.remember("user1".to_owned());
    HttpResponse::Found().header("location", "/").finish()
}

async fn logout(id: Identity) -> HttpResponse {
    id.forget();
    HttpResponse::Found().header("location", "/").finish()
}


#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .wrap(IdentityService::new(
                CookieIdentityPolicy::new(&rand::thread_rng().gen::<[u8; 32]>())
                    .name("test")
                    .max_age(60000)
                    .secure(false)
            ))
            // I added this part
            .configure(|cfg| {
                cfg.service(
                    web::scope("/cfg")
                        .service(web::resource("/login").route(web::post().to(login)))
                        .service(web::resource("/logout").to(logout))
                        .service(web::resource("/index").route(web::get().to(index)))
                );
            })
            .service(web::resource("/login").route(web::post().to(login)))
            .service(web::resource("/logout").to(logout))
            .service(web::resource("/").route(web::get().to(index)))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}
[dependencies]
actix-rt = "1.0.0"
actix-web = { version="2.0.0" }
actix-identity = "0.2.0"
rand = "0.7.3"

What happens

  • I expect to see Hello user1 on /cfg/index after posting to /login. I get Hello Anonymous instead.
  • If you see Hello user1, then send GET to / after that. You might get Hello Anonymous there.
  • In general. play with logging in at /login and sending GET to /cfg/index. Or go to / instead. Mix these four routes. You should get Hello Anonymous at some point. I don't see the whole pattern yet.

Is it a bug? If not, then please explain why does it work like this. I'm new to both rust and actix. I've checked out actix_identity sources and didn't find anything suspicious (I was looking for strange forget-like statements). My guess is that the service's value gets moved somewhere between App and configure parts and it's state being dropped. But it is too vague.

Context

I moved part of routes to external module. I added identity service so I could extract user information from request. And than I got this behavior. It's wrong because clients I use (browser and postman) are being randomly kicked out.

Your Environment

  • Win10
  • rustc 1.44.0 (49cae5576 2020-06-01)

actix-session incompatible with the new v4 beta

using actix-session like this

.wrap(
    CookieSession::signed(&decode(env::var("APP_KEY").unwrap()).unwrap())
        .domain(env::var("APP_URL").unwrap())
        .name("queue_rs")
        .path("/")
        .secure(false),
)

results in

error[E0277]: the trait bound `CookieSession: Transform<actix_web::app_service::AppRouting, ServiceRequest>` is not satisfied
   --> src/main.rs:268:17
    |
268 | /                 CookieSession::signed(&decode(env::var("APP_KEY").unwrap()).unwrap())
269 | |                     .domain(env::var("APP_URL").unwrap())
270 | |                     .name("queue_rs")
271 | |                     .path("/")
272 | |                     .secure(false),
    | |__________________________________^ the trait `Transform<actix_web::app_service::AppRouting, ServiceRequest>` is not implemented for `CookieSession`

deps:
actix-web = "4.0.0-beta.1"
actix-rt = "2.0.0-beta.1"
actix-files = "0.6.0-beta.1"
actix-session = "0.4.0"

Also great job on the tokio upgrade, i see you guys have been working hard to get that upgraded.

Compile the examples when running tests

Currently when tests are executed the various examples are not being compiled. Let's make sure to do this so the examples will be continuously built against the current versions of the crates they demonstrate. If any incompatibilities arise in the examples when changes are made to their crates we will be alerted in time.

Is it possible to user auth before uploading data to the server?

I implemented a small Service that uploads media with http-multipart. I also added bearer auth as middleware.

i noticed that the server only authenticates the user when all data has been uploaded, so if I upload a file, that is several 100MB in size I would wait a couple of minutes before getting rejected.

Is there a way to check if the user provided the correct token before uploading any form data?

actix-redis: Panicked at 'System is not running' in tests when using the latest actix-web and actix-rt crates

Expected Behavior

RedisSession::new should not panic when testing under actix_rt::test

Current Behavior

RedisSession::new panics when testing under actix_rt::test

running 1 test
thread 'test' panicked at 'System is not running', /home/dema/.cargo/registry/src/github.com-1ecc6299db9ec823/actix-rt-1.1.1/src/lib.rs:31:9

Possible Solution

Steps to Reproduce (for bugs)

Dependencies in Cargo.toml:

[dependencies]
actix-web = "3.3"
actix-redis = "0.9"

[dev-dependencies]
actix-rt = "2.0"

main.rs

use actix_redis::RedisSession;

#[actix_web::main]
async fn main() {
    let s = RedisSession::new("127.0.0.1:6379", &[0;32]);
}

#[cfg(test)]
#[actix_rt::test]
async fn test() {
    let s = RedisSession::new("127.0.0.1:6379", &[0;32]);
}
  1. cargo run (works)
  2. cargo test (panics)

Context

I tried using the latest actix_rt release for testing using the latest actix-redis release alongside the latest actix_web release

Your Environment

  • Rust Version (I.e, output of rustc -V): rustc 1.49.0 (e1884a8e3 2020-12-29)
  • Actix-* crate(s) Version:
    • actix-web v3.3.2
    • actix-session v0.4.0
    • actix-redis v0.9.1

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.