Giter Club home page Giter Club logo

sdk-rust's People

Contributors

335g avatar andrewwebber avatar ctron avatar dejanb avatar dependabot[bot] avatar dirkrusche avatar duglin avatar jakubnoga avatar jcrossley3 avatar k3rn31 avatar lazzaretti avatar markmandel avatar matzew avatar milenkovicm avatar minghuaw avatar no9 avatar pranav-bhatt avatar rkudryashov avatar slinkydeveloper avatar sunli829 avatar tottoto avatar upsuper avatar xiaoas 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

sdk-rust's Issues

Docs in reqwest, actix-web and rdkafka integration

At the moment our "subcrates" doesn't have any docs in the main crate file lib.rs, we should add a doc with a little code example to explain the features of the crate and some pointers to the main doc of cloudevents-sdk

Fails to parse event which has non-JSON data section with JSON content type

Assuming you have an event with:

{
  "datacontenttype": "application/json",
  "data_base64": "… non JSON …",
}

Then it fails to deserialize the event, as it tries to parse the value as JSON:

(None, Some(d), true) => Some(Data::Json(parse_json_data_base64!(d, E)?)),

Citing the spec:

When a CloudEvents is deserialized from JSON, the presence of the data_base64 member clearly indicates that the value is a Base64 encoded binary data, which the serializer MUST decode into a binary runtime data type.

So parsing this into JSON is OK I guess, but a fallback of Binary must also be possible IMHO if that fails.

Possible Serialization bug?

Hi All
Testing the tide websocket implementation using the example message from
https://github.com/cloudevents/spec/blob/master/json-format.md#32-examples

{
    "specversion" : "1.0",
    "type" : "com.example.someevent",
    "source" : "/mycontext",
    "id" : "A234-1234-1234",
    "time" : "2018-04-05T17:31:00Z",
    "comexampleextension1" : "value",
    "comexampleothervalue" : 5,
    "unsetextension": null,
    "datacontenttype" : "text/xml",
    "data" : "<much wow=\"xml\"/>"
}

Specifically this line 205e16a#diff-97633925b0ac8233888bd3bdc2313999cd86c04f1e7e56a62a8cb1e8d58ba5eaR50

let v: Event = serde_json::from_str(&message).unwrap(); 

fails with

thread 'async-std/runtime' panicked at 'called `Result::unwrap()` on an 
`Err` value: Error("data did not match any variant of untagged enum ExtensionValue", 
line: 0, column: 0)', src/main.rs:50:71

If I remove the property set to null "unsetextension": null, the message works as expected.

{
    "specversion" : "1.0",
    "type" : "com.example.someevent",
    "source" : "/mycontext",
    "id" : "A234-1234-1234",
    "time" : "2018-04-05T17:31:00Z",
    "comexampleextension1" : "value",
    "comexampleothervalue" : 5,
    "datacontenttype" : "text/xml",
    "data" : "<much wow=\"xml\"/>"
}

According to the docs null should be treated as unset or omitted
https://github.com/cloudevents/spec/blob/70823088e52b393b4251abd1ab03b6cfa233d427/json-format.md#22-type-system-mapping.

Do you have any preferences for which it should be?

Check the checklist of rust library design api

There is this nice checklist on things to do to develop a nice api in rust, we should check it out and see if there is room of improvements in our APIs https://rust-lang.github.io/api-guidelines/checklist.html

Rust API Guidelines Checklist

  • Naming (crate aligns with Rust naming conventions)
    • Casing conforms to RFC 430 ([C-CASE])
    • Ad-hoc conversions follow as_, to_, into_ conventions ([C-CONV]) #87
    • Getter names follow Rust convention ([C-GETTER]) #88
    • Methods on collections that produce iterators follow iter, iter_mut, into_iter ([C-ITER])
    • Iterator type names match the methods that produce them ([C-ITER-TY]) #89
    • Feature names are free of placeholder words ([C-FEATURE])
    • Names use a consistent word order ([C-WORD-ORDER]) #90
  • Interoperability (crate interacts nicely with other library functionality)
    • Types eagerly implement common traits ([C-COMMON-TRAITS])
      • Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug,
        Display, Default #91
    • Conversions use the standard traits From, AsRef, AsMut ([C-CONV-TRAITS])
    • Collections implement FromIterator and Extend ([C-COLLECT])
    • Data structures implement Serde's Serialize, Deserialize ([C-SERDE])
    • Types are Send and Sync where possible ([C-SEND-SYNC]) #90
    • Error types are meaningful and well-behaved ([C-GOOD-ERR]) #90
    • Binary number types provide Hex, Octal, Binary formatting ([C-NUM-FMT])
    • Generic reader/writer functions take R: Read and W: Write by value ([C-RW-VALUE])
  • Macros (crate presents well-behaved macros)
    • Input syntax is evocative of the output ([C-EVOCATIVE])
    • Macros compose well with attributes ([C-MACRO-ATTR])
    • Item macros work anywhere that items are allowed ([C-ANYWHERE])
    • Item macros support visibility specifiers ([C-MACRO-VIS])
    • Type fragments are flexible ([C-MACRO-TY])
  • Documentation (crate is abundantly documented)
    • Crate level docs are thorough and include examples ([C-CRATE-DOC]) #95
    • All items have a rustdoc example ([C-EXAMPLE])
    • Examples use ?, not try!, not unwrap ([C-QUESTION-MARK]) #95
    • Function docs include error, panic, and safety considerations ([C-FAILURE]) #95
    • Prose contains hyperlinks to relevant things ([C-LINK]) #95
    • Cargo.toml includes all common metadata ([C-METADATA]) #95
      • authors, description, license, homepage, documentation, repository,
        readme, keywords, categories
    • Crate sets html_root_url attribute "https://docs.rs/CRATE/X.Y.Z" ([C-HTML-ROOT]) #95
    • Release notes document all significant changes ([C-RELNOTES])
    • Rustdoc does not show unhelpful implementation details ([C-HIDDEN]) #95
  • Predictability (crate enables legible code that acts how it looks)
    • Smart pointers do not add inherent methods ([C-SMART-PTR])
    • Conversions live on the most specific type involved ([C-CONV-SPECIFIC])
    • Functions with a clear receiver are methods ([C-METHOD])
    • Functions do not take out-parameters ([C-NO-OUT])
    • Operator overloads are unsurprising ([C-OVERLOAD])
    • Only smart pointers implement Deref and DerefMut ([C-DEREF])
    • Constructors are static, inherent methods ([C-CTOR])
  • Flexibility (crate supports diverse real-world use cases)
    • Functions expose intermediate results to avoid duplicate work ([C-INTERMEDIATE])
    • Caller decides where to copy and place data ([C-CALLER-CONTROL])
    • Functions minimize assumptions about parameters by using generics ([C-GENERIC])
    • Traits are object-safe if they may be useful as a trait object ([C-OBJECT])
  • Type safety (crate leverages the type system effectively)
    • Newtypes provide static distinctions ([C-NEWTYPE])
    • Arguments convey meaning through types, not bool or Option ([C-CUSTOM-TYPE])
    • Types for a set of flags are bitflags, not enums ([C-BITFLAG])
    • Builders enable construction of complex values ([C-BUILDER])
  • Dependability (crate is unlikely to do the wrong thing)
    • Functions validate their arguments ([C-VALIDATE])
    • Destructors never fail ([C-DTOR-FAIL])
    • Destructors that may block have alternatives ([C-DTOR-BLOCK])
  • Debuggability (crate is conducive to easy debugging)
    • All public types implement Debug ([C-DEBUG]) #91
    • Debug representation is never empty ([C-DEBUG-NONEMPTY]) #91
  • Future proofing (crate is free to improve without breaking users' code)
    • Sealed traits protect against downstream implementations ([C-SEALED]) #95
    • Structs have private fields ([C-STRUCT-PRIVATE])
    • Newtypes encapsulate implementation details ([C-NEWTYPE-HIDE])
    • Data structures do not duplicate derived trait bounds ([C-STRUCT-BOUNDS])
  • Necessities (to whom they matter, they really matter)
    • Public dependencies of a stable crate are stable ([C-STABLE])
    • Crate and its dependencies have a permissive license ([C-PERMISSIVE])

Latest serde breaks cloudevents-sdk

Updating serde to latest breaks cloudevents-sdk

cargo build
   Compiling proc-macro2 v1.0.24
   Compiling unicode-xid v0.2.1
   Compiling syn v1.0.58
   Compiling autocfg v1.0.1
   Compiling libc v0.2.82
   Compiling serde_derive v1.0.119
   Compiling serde v1.0.119
   Compiling tinyvec_macros v0.1.0
   Compiling matches v0.1.8
   Compiling doc-comment v0.3.3
   Compiling getrandom v0.2.1
   Compiling ryu v1.0.5
   Compiling serde_json v1.0.61
   Compiling percent-encoding v2.1.0
   Compiling cfg-if v1.0.0
   Compiling match_cfg v0.1.0
   Compiling itoa v0.4.7
   Compiling base64 v0.12.3
   Compiling unicode-bidi v0.3.4
   Compiling tinyvec v1.1.0
   Compiling form_urlencoded v1.0.0
   Compiling num-traits v0.2.14
   Compiling num-integer v0.1.44
   Compiling quote v1.0.8
   Compiling time v0.1.43
   Compiling hostname v0.3.1
   Compiling uuid v0.8.2
   Compiling unicode-normalization v0.1.16
   Compiling ordered-float v1.1.1
   Compiling idna v0.2.0
   Compiling snafu-derive v0.6.10
   Compiling delegate-attr v0.2.9
   Compiling snafu v0.6.10
   Compiling url v2.2.0
   Compiling chrono v0.4.19
   Compiling serde-value v0.6.0
   Compiling cloudevents-sdk v0.3.0
error[E0603]: module `export` is private
   --> /home/awebber/.cargo/registry/src/github.com-1ecc6299db9ec823/cloudevents-sdk-0.3.0/src/event/data.rs:1:12
    |
1   | use serde::export::Formatter;
    |            ^^^^^^ private module
    |
note: the module `export` is defined here
   --> /home/awebber/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.119/src/lib.rs:275:5
    |
275 | use self::__private as export;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0603]: module `export` is private
   --> /home/awebber/.cargo/registry/src/github.com-1ecc6299db9ec823/cloudevents-sdk-0.3.0/src/event/spec_version.rs:2:12
    |
2   | use serde::export::Formatter;
    |            ^^^^^^ private module
    |
note: the module `export` is defined here
   --> /home/awebber/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.119/src/lib.rs:275:5
    |
275 | use self::__private as export;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0603`.
error: could not compile `cloudevents-sdk`

To learn more, run the command again with --verbose.

Current workaround is rolling back to serde version 1.0.118

See related fix teloxide/teloxide#328

[dependencies]
cloudevents-sdk = "0.3.0"
serde = { version="=1.0.118", features = ["derive"] }

Attributes iterator

Event should expose a function that allows to iterate over available attributes

Run examples code compilation in CI

At the moment all the examples doesn't compile on CI. We should at least run cargo check when somebody push a new PR to check if the examples break.

Refactor/consolidate header logic/macros/globals

There is a lot of redundant logic around headers for each binding that we can probably consolidate into a shared lib.

@slinkydeveloper I'm thinking I can replace the ATTRIBUTES_TO_HEADERS map with a simple function that returns strings rather than HeaderNames. That way, I can eliminate all the lazy_static! stuff. It would simplify the code considerably and I can't imagine it would have any significant impact on performance. Agree?

Explore traits to improve apis of http integration modules

Right now the APIs are:

event_to_request(input, client.post(&url))
  .unwrap()
  .send()

I think it would be nicer to have something like:

client.post(&url)
  .event(input).unwrap() // This still need to fail somehow
  .send()

This applies both to request and responses for both actix-web and reqwest modules

Use actix-web 4

Although actix-web 4 is only released as beta yet, it is required for the switch to tokio 1.

no default features for actix-web

If/when the actix-web dependency is updated to v3, the dependency in Cargo.toml should ideally be:

- actix-web = "3.0.2"
+ actix-web = { version = "3.0.2", default-features = false }

Restructure project to enable `Event` to impl `actix_web::{FromRequest, Responder}`

In order to take advantage of actix-web's Extractors and Responders, cloudevents::Event would have to implement a few actix-web traits, but that's impossible due to rustc --explain E0117: Only traits defined in the current crate can be implemented for arbitrary types.

After chatting with @slinkydeveloper and @ctron, one possible solution would be to combine all of the current web runtimes into a single crate where the user's desired runtime would be conditionally compiled in using a cargo feature.

This issue is to track the feasibility of doing that.

Allow relative URL for ce-source header

Hello there, brand new to Rust so take this with a pinch of salt.

I have an incredibly simple actix-web setup and as I was testing it I noticed that the ce-source/source header must be passed through as a full absolute URL, including scheme because this is being parsed via the URL module. From what I can tell from the CloudEvents spec, it seems like the source does not need to include the scheme or even the domain (looking at the 'Exemplary JSON Value' for the source attribute).

It appears though that when I pass a relative URL to the to_event function I see the following response:

Error while parsing a url: relative URL without a base

Absolute URL (including scheme) work fine.


In case you need it to replicate, attaching my code here:

use actix_web::{post, web, App, HttpRequest, HttpServer};
use cloudevents::{EventBuilder, EventBuilderV10};
use cloudevents_sdk_actix_web::{HttpResponseBuilderExt, HttpRequestExt};

#[post("/")]
async fn handler(req: HttpRequest, payload: web::Payload) -> Result<String, actix_web::Error> {
    let event = req.to_event(payload).await?;
    println!("Received Event: {:?}", event);
    Ok(format!("{:?}", event))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(handler))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}
[dependencies]
actix-web = "^3"
cloudevents-sdk = "0.3.0"
cloudevents-sdk-actix-web = "0.3.0"
curl -v "http://127.0.0.1:8080" \
  -X POST \
  -H "Ce-Specversion: 1.0" \
  -H "Ce-Type: dev.knative.samples.helloworld" \
  -H "Ce-Source: /helloworldsource" \
  -H "Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f79" \
   -H "Content-Type: application/json" \
  -d '{"msg":"Hello Knative!"}'

Test no_std environments

We should check if it's doable for the main crate cloudevents-sdk to compile in no_std environments, in order to use this sdk in restricted environments too. An example use case could be: send a cloudevent using mqtt from an iot device

EventBuilder should fail if user didn't set the mandatory values

EventBuilder now is implemented using Event. This is wrong because event always have default values for the mandatory fields, we should convert EventBuilders to store all attributes as optional (even the mandatory ones) and fail on build() if there are some missing mandatory attributes.

Additional context

Now both v1 and v03 modules has a module called builder which exposes this builder struct:

pub struct EventBuilder {
    event: Event,
}

This builder will always set the default values for Event, never failing when the EventBuilder is not filled with mandatory fields:

pub fn build(self) -> Event {
        self.event
    }

The EventBuilder should in fact look like (below example for v10, but similar should be for v03):

pub struct EventBuilder {
    id: Option<String>,
    ty: Option<String>,
    source: Option<Url>,
    datacontenttype: Option<String>,
    dataschema: Option<Url>,
    subject: Option<String>,
    time: Option<DateTime<Utc>>,
    data: Option<Data>,
    extensions: HashMap<String, ExtensionValue>,
}

And the build signature should be like:

pub fn build(self) -> Result<Event, BuildError>

Where build error explicit the missing mandatory fields

Event Data Structure

Data structures to represent CloudEvents that can be extended in future to support different cloudevents versions. Some examples:

We also need easy accessors to read cloudevents metadata, extensions and payload. An example to read and parse payload: https://github.com/slinkydeveloper/cloudevents-rust/blob/master/cloudevents-rust/src/event/payload.rs

Data structure could be immutable, so we builders to build them. For builders we can try to use https://docs.rs/crate/derive_builder/0.9.0

Tokio 1.0

We need to bump tokio to 1.0 and check for something broken

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.