Skip to content

Commit

Permalink
Rename omnipresent AuthenticationFailed error to NotPermitted
Browse files Browse the repository at this point in the history
The omnipresent AuthenticationFailed error variant, which used to map to
HTTP status 401 (Unauthorized) had not been hooked up for ages, after
Alpaca in their endless wisdom decided to move everything to using HTTP
status 403, causing ambiguity all over the place.
With this change we rename this variant to NotPermitted and map it to
HTTP status 403. As part of this work, we effectively replace/overlay
the recently introduced NotPermitted variants for the various data::v2
endpoint errors.
  • Loading branch information
d-e-s-o committed Dec 17, 2023
1 parent fcf858f commit c56d784
Show file tree
Hide file tree
Showing 9 changed files with 17 additions and 40 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ Unreleased
----------
- Removed `ApiError::code` member after endpoint reported errors stopped
returning it
- Added `NotPermitted` variant to various `data::v2` endpoint errors
- Renamed `AuthenticationFailed` variant of endpoint errors to
`NotPermitted`
- This variant is now used to signal a multitude of conditions,
including certain order submission issues


0.27.2
Expand Down
3 changes: 1 addition & 2 deletions src/api/v2/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,14 @@ mod tests {
/// Check that we get back the expected error when requesting account
/// data with invalid credentials.
#[test(tokio::test)]
#[ignore]
async fn request_account_with_invalid_credentials() {
let api_info = ApiInfo::from_parts(API_BASE_URL, "invalid", "invalid-too").unwrap();
let client = Client::new(api_info);
let result = client.issue::<Get>(&()).await;

let err = result.unwrap_err();
match err {
RequestError::Endpoint(GetError::AuthenticationFailed(_)) => (),
RequestError::Endpoint(GetError::NotPermitted(_)) => (),
e => panic!("received unexpected error: {e:?}"),
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/api/v2/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,14 @@ mod tests {
/// Check that we get back the expected error when requesting the
/// market clock with invalid credentials.
#[test(tokio::test)]
#[ignore]
async fn request_clock_with_invalid_credentials() {
let api_info = ApiInfo::from_parts(API_BASE_URL, "invalid", "invalid-too").unwrap();
let client = Client::new(api_info);
let result = client.issue::<Get>(&()).await;

let err = result.unwrap_err();
match err {
RequestError::Endpoint(GetError::AuthenticationFailed(_)) => (),
RequestError::Endpoint(GetError::NotPermitted(_)) => (),
e => panic!("received unexpected error: {e:?}"),
}
}
Expand Down
19 changes: 1 addition & 18 deletions src/api/v2/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -717,14 +717,6 @@ Endpoint! {
/* 200 */ OK,
],
Err => PostError, [
/// The order submission was not permitted. That can have multiple
/// reasons, including (but not necessarily limited to):
/// - not enough funds are available
/// - the order is of a certain order type that cannot be submitted
/// at this time of day (e.g., market-open orders must be
/// submitted after 7:00pm and before 9:28am and will be rejected
/// at other times)
/* 403 */ FORBIDDEN => NotPermitted,
/// Some data in the request was invalid.
/* 422 */ UNPROCESSABLE_ENTITY => InvalidInput,
]
Expand Down Expand Up @@ -756,14 +748,6 @@ Endpoint! {
/* 200 */ OK,
],
Err => PatchError, [
/// The order change was not permitted. That can have multiple
/// reasons, including (but not necessarily limited to):
/// - not enough funds are available
/// - the order is of a certain order type that cannot be submitted
/// at this time of day (e.g., market-open orders must be
/// submitted after 7:00pm and before 9:28am and will be rejected
/// at other times)
/* 403 */ FORBIDDEN => NotPermitted,
/// No order was found with the given ID.
/* 404 */ NOT_FOUND => NotFound,
/// Some data in the request was invalid.
Expand Down Expand Up @@ -1067,8 +1051,7 @@ mod tests {

// When an extended hours order is submitted between 6pm and 8pm,
// the Alpaca API reports an error:
// > {"code":42210000,"message":"extended hours orders between 6:00pm
// > and 8:00pm is not supported"}
// > {"message":"extended hours orders between 6:00pm and 8:00pm is not supported"}
//
// So we need to treat this case specially.
let result = test(true).await;
Expand Down
3 changes: 0 additions & 3 deletions src/data/v2/bars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,6 @@ Endpoint! {
Err => GetError, [
/// A query parameter was invalid.
/* 400 */ BAD_REQUEST => InvalidInput,
/// The request was not permitted. Possible reasons include usage of
/// the SIP feed without having the corresponding subscription.
/* 403 */ FORBIDDEN => NotPermitted,
]

fn base_url() -> Option<Str> {
Expand Down
3 changes: 0 additions & 3 deletions src/data/v2/last_quotes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,6 @@ EndpointNoParse! {
/// The provided symbol was invalid or not found or the data feed is
/// not supported.
/* 400 */ BAD_REQUEST => InvalidInput,
/// The request was not permitted. Possible reasons include usage of
/// the SIP feed without having the corresponding subscription.
/* 403 */ FORBIDDEN => NotPermitted,
]

fn base_url() -> Option<Str> {
Expand Down
3 changes: 0 additions & 3 deletions src/data/v2/quotes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ Endpoint! {
Err => GetError, [
/// Some of the provided data was invalid or not found.
/* 400 */ BAD_REQUEST => InvalidInput,
/// The request was not permitted. Possible reasons include usage of
/// the SIP feed without having the corresponding subscription.
/* 403 */ FORBIDDEN => NotPermitted,
]

fn base_url() -> Option<Str> {
Expand Down
3 changes: 0 additions & 3 deletions src/data/v2/trades.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,6 @@ Endpoint! {
Err => GetError, [
/// A query parameter was invalid.
/* 400 */ BAD_REQUEST => InvalidInput,
/// The request was not permitted. Possible reasons include usage of
/// the SIP feed without having the corresponding subscription.
/* 403 */ FORBIDDEN => NotPermitted,
]

fn base_url() -> Option<Str> {
Expand Down
15 changes: 10 additions & 5 deletions src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,16 @@ macro_rules! EndpointNoParse {
// Every request can result in an authentication failure or fall
// prey to the rate limit and so we include these variants into
// all our error definitions.
/// Authentication failed for the request.
// TODO: This status actually got changed to 403, which now
// shadows other error conditions by specific endpoints
// (e.g., insufficient funds when submitting an order).
/* 401 */ UNAUTHORIZED => AuthenticationFailed,
/// The request was not permitted.
///
/// This can have a multitude of reasons, including invalid
/// credentials or the (potentially implicit) request of SIP
/// data through the data APIs when only an IEX subscription is
/// available.
/// Order submission/change failure (e.g., due to insufficient
/// funds or time constraint violations) is also expressed this
/// way.
/* 403 */ FORBIDDEN => NotPermitted,
/// The rate limit was exceeded, causing the request to be
/// denied.
/* 429 */ TOO_MANY_REQUESTS => RateLimitExceeded,
Expand Down

0 comments on commit c56d784

Please sign in to comment.