Made this whole thing somewhat publicly presentable.

Now that's not to say I cleaned up the source code, who knows what the
heck is in there...
This commit is contained in:
ForeverPyrite
2025-09-19 23:31:53 -04:00
parent 844c9eea6e
commit f92026698c
12 changed files with 2355 additions and 87 deletions

View File

@@ -2,6 +2,7 @@
name = "aws_sigv4"
version = "0.1.0"
edition = "2024"
description = "Minimal-dependancy library to sign requests via AWS's SigV4."
[lib]

View File

@@ -1,78 +1,12 @@
# aws_signing library
Yeah so this is a library for signing things with AWS SigV4.
Pretty straightforward.
In fact, there is are only 3 methods on the public API
1. to make the client
2. Change the client region (cause why not?)
3. To transform an unsigned request that will be sent to an AWS compatible server to one with proper SigV4 headers
(With this wording, should I take a mutable reference to headers instead of...hmmm, we will see if I get bored enough to improve it myself.)
If I'm being completely honest, this was part of my own `r2client` that I wrote, which is uses S3
So I don't imagine that I come back to this to actually make a proper AWS Signing library.
I could imagine it being useful to *someone* who also wants to make an AWS abstraction that doesn't have 2 **BILLION** dependences.
## Usage
wait that's what the doc comments and `cargo doc` command is for lmao,
guess I'll get rid of this block
### Unexpected Errors
If you're getting errors related to invalid signatures and you're thinking "It's probably that damn crate I'm using from that newbie!",
you're probably right.
If you got here because crates.io search brought you here, nice.
Didn't mean for that to happen, sorry!
There are much more developed options out there, like [reqsign](https://github.com/apache/opendal-reqsign), which will also handle more
of the service related things for you.
Alternatively, you can try to stick with this crate (mistake)
Using log level trace with whatever logging crate you use will print out all steps of the AWS signing process, so you can follow along
with your favorite documentation/examples and figure out where things go wrong.
With this you can either raise an issue, or review the code yourself to implement a working solution.
# aws_sigv4
Used by the r2client's R2Client to sign requests.
So cool, ikr?
## Todo
- [ ] Create unit tests
- [ ] Add option for session keys
- [ ] Additional client or whatever for weirdos who want to use SigV4a
- [ ] Perhaps drop `http` as a dependency?
- [ ] Alternatively, have users pass a mutable reference to a HeaderMap instead of cloning and returning a new one.
- This can kinda hurt ease of use...maybe, but I feel like the slight performance gain and easier management of custom headers makes it worth.
- That's also acting like the crate is mature enough to do anything but provide the minimal headers for SigV4
- [ ] SigV4a
- Is this even really used?
## Contributing
What.
This crate is supposed to be a really simple way to sign AWS request headers and nothing else.
Again, I created it for my Cloudflare R2 (AWS S3) client and I imagine there are a few gaps for other services,
as well as some exceptions to the general programmatic things I saw in the documentation.
If you'd like to help improve it, maybe to make sign requests for some other AWS service, then I'd
appreciate if as specific unit test was added to ensure functionality.
This should be along with the other unit tests remaining intact and passing (unless they are blatantly incompatible
with some AWS documentation)
The code base (one lib.rs file) is pretty straightforward, it very directly follows the outline that AWS's SigV4 documentation provides,
explicitly containing all prerequisite functions and having a function call for all 5 of the steps.
I did this since the other examples were hard to follow, just a chunk of code that doesn't explain itself at any point.
All prerequisite functions, along with functions that don't require any of the keys/credential fields (in SigV4Credentials)
are defined outside of the struct.
Gl;hf
# welp
figure I'd try my hand at writing some public stuff like this, even though I'm not planing on publishing this publicly, only
compiled in the r2client.
I feel...okay about it.
I still feel like this stuff will be so small no matter what that I can still put a little personality into it.
I am incredibly verbose, shocking I know, but I think that's a bad thing.
I should be more brief, and then more verbose when relevant within the code.
Outside of that though, I think this is...fine.
I just need to get better at less yapping.
I really think this crate is too intermingled with the R2 Client to be useful to anyone else, really, although I think this was
*fine* for organizational purposes.
And who knows.
Maybe I'll need it again.
- [ ] Replace the http::Uri with a &str and parse it instead...duh (unless that doesn't exist, but it 100% does)
- [ ] Use a mutable reference to a HeaderMap instead of that UGLY UGLY Vec<(String, String)> format
- Although I'm not sure how much better this will be with the whole sort in alphabetical order, but it'll be a hell of a lot cooler
- [ ] The unit tests lol
- [ ] Introduce the option for session tokens
- [ ] SigV4a?

View File

@@ -1,3 +1,10 @@
oh hi
I haven't done the unit tests yet.
I thought it wouldn't work but then it just randomly worked after not working with no changes
which was really weird
I should probably still put the unit tests in there, cause they kinda just...fail...
Example: GET Object
The following example gets the first 10 bytes of an object (test.txt) from examplebucket. For more information about the API action, see GetObject.

View File

@@ -371,6 +371,13 @@ mod tests {
bucket,
file_key
);
// "Two copies for the same thing? That's stupid!" I agree.
// I want people to be able to use whatever HTTP Client they want, but reqwest doesn't like
// that idea.
// It dawns upon me that I can just accept a string, try to parse it to http::Uri, and just
// use it internally.
// damn.
// crazy.
let endpoint: http::Uri = url.parse().unwrap();
let headers = vec![("host".to_string(), endpoint.host().unwrap().to_owned())];