cloudevents/sdk-rust

Allow relative URL for ce-source header

jackturnbull opened this issue · 5 comments

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!"}'

I'm looking at url library now, and it sounds like their url type cannot contain relative urls... Do you have any viable solution to propose? Like an alternative lib to use for urls?

I'm afraid I don't (sorry!) I'm only really dipping my toes into Rust as a learning exercise. If it's only me facing this though, I'm fine for this to be closed.

I'm afraid I don't (sorry!) I'm only really dipping my toes into Rust as a learning exercise. If it's only me facing this though, I'm fine for this to be closed.

Nono this shouldn't be closed, it's a spec incompatibility, it's rather an important bug 😄

ctron commented

I just ran into this. I think this is a critical issue, as this doesn't allow you to consume spec conformant messages!

I guess if the URL struct can't handle relative URLs, then using a String instead might be a reasonable alternative.

The spec says this field must be a "URI-reference", which it defines as: https://tools.ietf.org/html/rfc3986#section-4.1. Which says:

A URI-reference is either a URI or a relative reference.

It also brings in (Append B) a regular expression for validating this:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?

So I guess there are two options:

  1. Just use a String
  2. Use an enum (e.g. Source), with two variants: Uri(Url) and Relative(String)

The latter being something like this:

pub enum Source {
  Uri(Url),
  Relative(String),
}

You could also let it implement something like ToString to bring this back as a String for simpler processing.

As this is a current blocker for us, I would be willing to help out here.

I wonder, how about just using String now and then, maybe in future, figure out if we can find a better library for relative and absolute uris? Are you willing to work on this @ctron?