Skip to content

Commit 862f9a7

Browse files
committed
added explicit ExecutionTime expiration
1 parent c8e0a41 commit 862f9a7

File tree

4 files changed

+101
-16
lines changed

4 files changed

+101
-16
lines changed

stackslib/src/net/api/fastcallreadonly.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ use crate::net::api::callreadonly::{
3333
};
3434
use crate::net::http::{
3535
parse_json, Error, HttpContentType, HttpNotFound, HttpRequest, HttpRequestContents,
36-
HttpRequestPreamble, HttpResponse, HttpResponseContents, HttpResponsePayload,
37-
HttpResponsePreamble,
36+
HttpRequestPreamble, HttpRequestTimeout, HttpResponse, HttpResponseContents,
37+
HttpResponsePayload, HttpResponsePreamble,
3838
};
3939
use crate::net::httpcore::{
4040
request, HttpPreambleExtensions, HttpRequestContentsExtensions, RPCRequestHandler,
@@ -288,6 +288,14 @@ impl RPCRequestHandler for RPCFastCallReadOnlyRequestHandler {
288288
cause: Some("NotReadOnly".to_string()),
289289
}
290290
}
291+
Unchecked(CheckErrors::ExecutionTimeExpired) => {
292+
return StacksHttpResponse::new_error(
293+
&preamble,
294+
&HttpRequestTimeout::new("ExecutionTime expired".to_string()),
295+
)
296+
.try_into_contents()
297+
.map_err(NetError::from)
298+
}
291299
_ => CallReadOnlyResponse {
292300
okay: false,
293301
result: None,

stackslib/src/net/api/tests/fastcallreadonly.rs

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -328,23 +328,72 @@ fn test_try_make_response_free_cost_tracker() {
328328
},
329329
);
330330

331-
// confirmed tip
332331
let response = responses.remove(0);
333-
debug!(
334-
"Response:\n{}\n",
335-
std::str::from_utf8(&response.try_serialize().unwrap()).unwrap()
332+
let (preamble, contents) = response.destruct();
333+
334+
assert_eq!(preamble.status_code, 408);
335+
336+
let body: String = contents.try_into().unwrap();
337+
assert_eq!(body, "ExecutionTime expired");
338+
}
339+
340+
#[test]
341+
fn test_wrong_auth() {
342+
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 33333);
343+
344+
let mut requests = vec![];
345+
346+
// query confirmed tip
347+
let mut request = StacksHttpRequest::new_fastcallreadonlyfunction(
348+
addr.into(),
349+
StacksAddress::from_string("ST2DS4MSWSGJ3W9FBC6BVT0Y92S345HY8N3T6AV7R").unwrap(),
350+
"hello-world".try_into().unwrap(),
351+
StacksAddress::from_string("ST2DS4MSWSGJ3W9FBC6BVT0Y92S345HY8N3T6AV7R")
352+
.unwrap()
353+
.to_account_principal(),
354+
None,
355+
"ro-confirmed".try_into().unwrap(),
356+
vec![],
357+
TipRequest::UseLatestAnchoredTip,
336358
);
359+
request.add_header("authorization".into(), "wrong".into());
337360

338-
assert_eq!(
339-
response.preamble().get_canonical_stacks_tip_height(),
340-
Some(1)
361+
requests.push(request);
362+
363+
let mut responses = test_rpc(function_name!(), requests);
364+
365+
let response = responses.remove(0);
366+
let (preamble, contents) = response.destruct();
367+
368+
assert_eq!(preamble.status_code, 401);
369+
}
370+
371+
#[test]
372+
fn test_missing_auth() {
373+
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 33333);
374+
375+
let mut requests = vec![];
376+
377+
// query confirmed tip
378+
let request = StacksHttpRequest::new_fastcallreadonlyfunction(
379+
addr.into(),
380+
StacksAddress::from_string("ST2DS4MSWSGJ3W9FBC6BVT0Y92S345HY8N3T6AV7R").unwrap(),
381+
"hello-world".try_into().unwrap(),
382+
StacksAddress::from_string("ST2DS4MSWSGJ3W9FBC6BVT0Y92S345HY8N3T6AV7R")
383+
.unwrap()
384+
.to_account_principal(),
385+
None,
386+
"ro-confirmed".try_into().unwrap(),
387+
vec![],
388+
TipRequest::UseLatestAnchoredTip,
341389
);
342390

343-
let resp = response.decode_call_readonly_response().unwrap();
391+
requests.push(request);
344392

345-
assert!(!resp.okay);
346-
assert!(resp.result.is_none());
347-
assert!(resp.cause.is_some());
393+
let mut responses = test_rpc(function_name!(), requests);
394+
395+
let response = responses.remove(0);
396+
let (preamble, contents) = response.destruct();
348397

349-
assert_eq!(resp.cause.unwrap(), "Unchecked(ExecutionTimeExpired)");
398+
assert_eq!(preamble.status_code, 401);
350399
}

stackslib/src/net/http/error.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub fn http_error_from_code_and_text(code: u16, message: String) -> Box<dyn Http
128128
402 => Box::new(HttpPaymentRequired::new(message)),
129129
403 => Box::new(HttpForbidden::new(message)),
130130
404 => Box::new(HttpNotFound::new(message)),
131+
408 => Box::new(HttpRequestTimeout::new(message)),
131132
500 => Box::new(HttpServerError::new(message)),
132133
501 => Box::new(HttpNotImplemented::new(message)),
133134
503 => Box::new(HttpServiceUnavailable::new(message)),
@@ -292,6 +293,33 @@ impl HttpErrorResponse for HttpNotFound {
292293
}
293294
}
294295

296+
/// HTTP 408
297+
pub struct HttpRequestTimeout {
298+
error_text: String,
299+
}
300+
301+
impl HttpRequestTimeout {
302+
pub fn new(error_text: String) -> Self {
303+
Self { error_text }
304+
}
305+
}
306+
307+
impl HttpErrorResponse for HttpRequestTimeout {
308+
fn code(&self) -> u16 {
309+
408
310+
}
311+
fn payload(&self) -> HttpResponsePayload {
312+
HttpResponsePayload::Text(self.error_text.clone())
313+
}
314+
fn try_parse_response(
315+
&self,
316+
preamble: &HttpResponsePreamble,
317+
body: &[u8],
318+
) -> Result<HttpResponsePayload, Error> {
319+
try_parse_error_response(preamble.status_code, preamble.content_type, body)
320+
}
321+
}
322+
295323
/// HTTP 500
296324
pub struct HttpServerError {
297325
error_text: String,

stackslib/src/net/http/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ pub use crate::net::http::common::{
3737
};
3838
pub use crate::net::http::error::{
3939
http_error_from_code_and_text, http_reason, HttpBadRequest, HttpError, HttpErrorResponse,
40-
HttpForbidden, HttpNotFound, HttpNotImplemented, HttpPaymentRequired, HttpServerError,
41-
HttpServiceUnavailable, HttpUnauthorized,
40+
HttpForbidden, HttpNotFound, HttpNotImplemented, HttpPaymentRequired, HttpRequestTimeout,
41+
HttpServerError, HttpServiceUnavailable, HttpUnauthorized,
4242
};
4343
pub use crate::net::http::request::{
4444
HttpRequest, HttpRequestContents, HttpRequestPayload, HttpRequestPreamble,

0 commit comments

Comments
 (0)