Skip to content

Commit

Permalink
refs #4796 do not try to get a new token if the token was just issued
Browse files Browse the repository at this point in the history
  • Loading branch information
davidnich committed Sep 22, 2023
1 parent 94fb6d6 commit af92683
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 13 deletions.
25 changes: 15 additions & 10 deletions bin/rest
Expand Up @@ -251,7 +251,11 @@ class RestCmd {
rest.setConnectionPath();
}
} catch (hash<ExceptionInfo> ex) {
stderr.printf("connection %y: %s: %s: %s\n", opt.conn, get_ex_pos(ex), ex.err, ex.desc);
if (opt.fullex) {
stderr.printf("%s\n", get_exception_string(ex));
} else {
stderr.printf("connection %y: %s: %s: %s\n", opt.conn, get_ex_pos(ex), ex.err, ex.desc);
}
exit(1);
}
} else {
Expand Down Expand Up @@ -333,36 +337,37 @@ class RestCmd {
showRestResponse(info, h.body, opt);
}

on_error rethrow $1.err, sprintf("%s (using url: %y request path: %y)", $1.desc, rest.getURL(), request_path ?? "");
on_error rethrow $1.err, sprintf("%s (using url: %y request path: %y)", $1.desc, rest.getURL(),
request_path ?? "");
h = rest.doRequest(meth, request_path ?? "", body, \info);
if (!opt.lit) {
printf("%N\n", h.body);
}
} catch (hash<ExceptionInfo> ex) {
if (opt.fullex) {
printf("%s\n", get_exception_string(ex));
stderr.printf("%s\n", get_exception_string(ex));
} else {
if (ex.err == "DESERIALIZATION-ERROR"
&& info."response-headers"."content-type" == "text/html"
&& info."response-body") {
printf("%s\n%s\n", info."response-uri", html_decode(info."response-body"));
stderr.printf("%s\n%s\n", info."response-uri", html_decode(info."response-body"));
} else {
printf("%s: %s: %s", rest.getURL(), ex.err, ex.desc);
stderr.printf("%s: %s: %s", rest.getURL(), ex.err, ex.desc);
if (ex.arg) {
print(": ");
stderr.print(": ");
if (ex.arg.body.typeCode() == NT_STRING) {
trim ex.arg.body;
print(ex.arg.body);
stderr.print(ex.arg.body);
} else {
if (ex.arg.typeCode() == NT_STRING) {
trim ex.arg;
printf("%y", ex.arg);
stderr.printf("%y", ex.arg);
} else {
printf("%y", ex.arg);
stderr.printf("%y", ex.arg);
}
}
}
print("\n");
stderr.print("\n");
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions doxygen/lang/900_release_notes.dox.tmpl
Expand Up @@ -8,6 +8,9 @@
Major release of %Qore

@subsection qore_2_0_0_bug_fixes Bug Fixes in Qore
- <a href="../../modules/RestClient/html/index.html">RestClient</a>
- do not try to get another OAuth2 token if the token was just retrieved
(<a href="https://github.com/qorelanguage/qore/issues/4796">issue 4796</a>)
- fixed an extraneous \c SOCKET-NOT-OPEN exception when running socket callbacks after a socket was closed
(<a href="https://github.com/qorelanguage/qore/issues/4795">issue 4795</a>)

Expand Down
21 changes: 18 additions & 3 deletions qlib/RestClient.qm
Expand Up @@ -55,7 +55,7 @@
%endtry

module RestClient {
version = "2.0";
version = "2.0.1";
desc = "user module for calling REST services";
author = "David Nichols <david@qore.org>";
url = "http://qore.org";
Expand Down Expand Up @@ -132,6 +132,10 @@ printf("%N\n", ans.body);

@section restclientrelnotes Release Notes

@subsection restclientv2_0_1 RestClient v2.0.1
- do not try to get another OAuth2 token if the token was just retrieved
(<a href="https://github.com/qorelanguage/qore/issues/4796">issue 4796</a>)

@subsection restclientv2_0 RestClient v2.0
- implemented support for OAuth2 authorization flows
(<a href="https://github.com/qorelanguage/qore/issues/4766">issue 4766</a>)
Expand Down Expand Up @@ -460,6 +464,9 @@ public class RestClient inherits Qore::HTTPClient, Logger::LoggerWrapper, Connec
# format (ex: the Salesforce OAuth2 server)
"Accept": MimeTypeFormUrlEncoded + "," + MimeTypeJson,
};

#! Minimum time between OAuth2 token requests
const MinimumTokenRefresh = 1m;
}

private {
Expand Down Expand Up @@ -505,6 +512,8 @@ public class RestClient inherits Qore::HTTPClient, Logger::LoggerWrapper, Connec
string refresh_token;
#! If OAuth2 tokens should be automatically refreshed
bool oauth2_auto_refresh = True;
#! Last timestamp for token acquisition
date token_timestamp;
}

#! calls the base class HTTPClient constructor and optionally connects to the REST server
Expand Down Expand Up @@ -1287,7 +1296,8 @@ hash<auto> ans = rest.doRequest("DELETE", "/orders/1");
return doRequestIntern(m, path, body, \info, decode_errors, hdr);
} catch (hash<ExceptionInfo> ex) {
# in case of a 401 error, try to get a new token
if (info."response-code" == 401 && oauth2_grant_type && oauth2_auto_refresh) {
if (info."response-code" == 401 && oauth2_grant_type && oauth2_auto_refresh
&& ((now_us() - token_timestamp) > MinimumTokenRefresh)) {
on_error {
rethrow ex.err, ex.desc, ex.arg;
};
Expand Down Expand Up @@ -1419,6 +1429,7 @@ hash<auto> ans = rest.doRequest("DELETE", "/orders/1");
if (update_options && new_opts) {
doUpdateOptions(self, new_opts);
}
token_timestamp = now_us();
return h;
}

Expand Down Expand Up @@ -1536,7 +1547,7 @@ hash<auto> ans = rest.doRequest("DELETE", "/orders/1");
});
}

#! Perform OAuth2 password authentication
#! Perform OAuth2 authentication
/** @since %RestClient 2.0
*/
private hash<auto> oauth2Auth(hash<auto> login, *reference<hash<auto>> info) {
Expand All @@ -1552,6 +1563,10 @@ hash<auto> ans = rest.doRequest("DELETE", "/orders/1");
setUserPassword(username, self.password);
}

# remove tokens and Authorization header
remove token;
remove headers.Authorization;

# temporarily remove any schema for the OAuth2 call
AbstractRestSchemaValidator v;
if (!(validator instanceof NullRestSchemaValidator)) {
Expand Down

0 comments on commit af92683

Please sign in to comment.