Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[web] fix rest-test issues #593

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 8 additions & 24 deletions src/rest/resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,6 @@ Resource::Resource(ControllerOpenThread *aNcp)
mResourceCallbackMap.emplace(OT_REST_RESOURCE_PATH_DIAGNOETIC, &Resource::HandleDiagnosticCallback);
}

void Resource::Init(void)
{
}

void Resource::Handle(Request &aRequest, Response &aResponse) const
{
std::string url = aRequest.GetUrl();
Expand Down Expand Up @@ -519,33 +515,21 @@ void Resource::UpdateDiag(std::string aKey, std::vector<otNetworkDiagTlv> &aDiag

void Resource::Diagnostic(const Request &aRequest, Response &aResponse) const
{
otbrError error = OTBR_ERROR_NONE;
OT_UNUSED_VARIABLE(aRequest);

struct otIp6Address rloc16address = *otThreadGetRloc(mInstance);
struct otIp6Address multicastAddress;

VerifyOrExit(otThreadSendDiagnosticGet(mInstance, &rloc16address, kAllTlvTypes, sizeof(kAllTlvTypes),
&Resource::DiagnosticResponseHandler,
const_cast<Resource *>(this)) == OT_ERROR_NONE,
error = OTBR_ERROR_REST);
VerifyOrExit(otIp6AddressFromString(kMulticastAddrAllRouters, &multicastAddress) == OT_ERROR_NONE,
error = OTBR_ERROR_REST);
VerifyOrExit(otThreadSendDiagnosticGet(mInstance, &multicastAddress, kAllTlvTypes, sizeof(kAllTlvTypes),
&Resource::DiagnosticResponseHandler,
const_cast<Resource *>(this)) == OT_ERROR_NONE,
error = OTBR_ERROR_REST);
SuccessOrExit(otThreadSendDiagnosticGet(mInstance, &rloc16address, kAllTlvTypes, sizeof(kAllTlvTypes),
&Resource::DiagnosticResponseHandler, const_cast<Resource *>(this)));
SuccessOrExit(otIp6AddressFromString(kMulticastAddrAllRouters, &multicastAddress));
SuccessOrExit(otThreadSendDiagnosticGet(mInstance, &multicastAddress, kAllTlvTypes, sizeof(kAllTlvTypes),
&Resource::DiagnosticResponseHandler, const_cast<Resource *>(this)));

exit:

if (error == OTBR_ERROR_NONE)
{
aResponse.SetStartTime(steady_clock::now());
aResponse.SetCallback();
}
else
{
ErrorHandler(aResponse, HttpStatusCode::kStatusInternalServerError);
}
aResponse.SetStartTime(steady_clock::now());
aResponse.SetCallback();
Comment on lines -540 to +532
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, what happens if we fail in this function? Simply ignore the error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that It may fail when node is detached or no buffer for message.

So I think one solution is to define more HTTP status code according to these newly added error code, I think I could do it after #532 is merged.

Another solution is like this, we ignore all errors(more simple, but still reasonable).

For one thing, it could address the no buffer problem - although we fail in this API call, if we have diagnostic information(received in 4s but due to another call) left in resource, this information is still valid and could be sent as response.
For another thing, we could just view empty response as "some issues happen, we can't get anything now".

Copy link
Member

@wgtdkp wgtdkp Oct 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simply ignore the error?

@tttttangTH Is this true for your changes? I didn't see why we cannot handle the possible failures in this PR. It looks to me that keeping

else
    {
        ErrorHandler(aResponse, HttpStatusCode::kStatusInternalServerError);
    }

should just work. Why did you remove this error handler?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because if we call otThreadSendDiagnosticGet too many times within a specific period, we will get a no buffer error for this call( for example, when we send 10 requests for diagnostics concurrently , the no buffer error usually occurs).

But actually I prefer not viewing it as an error for HTTP response because the reason for calling otThreadSendDiagnosticGet each time when the server received a request for diagnostics is to update the information we maintained(we have a hash table to record all the diagnostic information we received within 4 seconds). If we have a 'no buffer' error, it means we have call the API many times recently so information in the hash table is almost the latest.

I know the right way to deal with this problem is to make an exception for no buffer rather than remove the error handler. I expect to do this after #532 because I think I may need to rewrite error handler of all RESTful API according to the modifications in #532 . So here I just ignore it currently.

Copy link
Member

@simonlingoogle simonlingoogle Oct 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is no buffer error not good for such situation? I think no buffer error was exactly what happened and should be reflected by the HTTP response.

Maybe we can return 507 Insufficient Storage for no buffer error.

But if the test is sending too much requests and is expecting no buffer error to happen sometimes, the test client can conclude with success even if there are some no buffer errors.

Thoughts? @tttttangTH @wgtdkp

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tttttangTH You should not just remove the error handler. You can at least add a log for this error.

I know the right way to deal with this problem is to make an exception for no buffer rather than remove the error handler. I expect to do this after #532 because I think I may need to rewrite error handler of all RESTful API according to the modifications in #532 .

I don't see why we need to wait for #532. Are there any REST feature that depends on #532?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have't found any other feature depend on #532 , but it seems we won't catch no buffer at otThreadSetReceiveDiagnosticGetCallback before #532 is applied.

I noticed no buffer before when when I wrote this API, at that time, no buffer was just an Info, and I have chosen to ignore it at that time. But It‘s thoughtless for me to just remove the error handler here.

Copy link
Member

@wgtdkp wgtdkp Oct 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need to address it in this PR: the function name SetCallback is bad... I would expect this function accepts a callback function as an argument but it is actually a flag indicates whether we have/enable callback. Can we rename to SetHasCallback?

Copy link
Contributor Author

@tttttangTH tttttangTH Oct 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will do it in #537

}

void Resource::DiagnosticResponseHandler(otError aError,
Expand Down
7 changes: 0 additions & 7 deletions src/rest/resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,6 @@ class Resource
*/
Resource(ControllerOpenThread *aNcp);

/**
* This method initialize the Resource handler.
*
*
*/
void Init(void);

/**
* This method is the main entry of resource handler, which find corresponding handler according to request url
* find the resource and set the content of response.
Expand Down
1 change: 0 additions & 1 deletion src/rest/rest_web_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ RestWebServer *RestWebServer::GetRestWebServer(ControllerOpenThread *aNcp)

void RestWebServer::Init(void)
{
mResource.Init();
InitializeListenFd();
}

Expand Down
4 changes: 4 additions & 0 deletions tests/rest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ set_tests_properties(rest-server PROPERTIES
set_tests_properties(rest-server PROPERTIES
LABELS "TESTREST"
)

set_tests_properties(rest-server PROPERTIES
TIMEOUT 60
)
6 changes: 6 additions & 0 deletions tests/rest/test-rest-server
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ wait
EOF
trap on_exit EXIT
sleep 5
sudo "${CMAKE_BINARY_DIR}"/third_party/openthread/repo/src/posix/ot-ctl factoryreset
sleep 1
sudo "${CMAKE_BINARY_DIR}"/third_party/openthread/repo/src/posix/ot-ctl ifconfig up
sleep 1
sudo "${CMAKE_BINARY_DIR}"/third_party/openthread/repo/src/posix/ot-ctl thread start
sleep 3
sudo python3 "${CMAKE_CURRENT_SOURCE_DIR}"/test_rest.py
}

Expand Down
11 changes: 7 additions & 4 deletions tests/rest/test_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ def assert_is_ipv6_address(string):
assert (type(ipaddress.ip_address(string)) is ipaddress.IPv6Address)

def get_data_from_url(url, result, index):
response = urllib.request.urlopen(urllib.request.Request(url))
body = response.read()
data = json.loads(body)
result[index] = data

try:
response = urllib.request.urlopen(urllib.request.Request(url))
body = response.read()
data = json.loads(body)
result[index] = data
except urllib.error.HTTPError as e:
print(e.code)

def get_error_from_url(url, result, index):
try:
Expand Down