api: return 404 for alloc FS list/stat endpoints (#11482)

* api: return 404 for alloc FS list/stat endpoints

If the alloc filesystem doesn't have a file requested by the List
Files or Stat File API, we currently return a HTTP 500 error with the
expected "file not found" error message. Return a HTTP 404 error
instead.

* update FS Handler

Previously the FS handler would interpret a 500 status as a 404
in the adapter layer by checking if the response body contained
the text  or is the response status
was 500 and then throw an error code for 404.

Co-authored-by: Jai Bhagat <jaybhagat841@gmail.com>
This commit is contained in:
Tim Gross 2021-11-17 11:15:07 -05:00 committed by GitHub
parent 863486ffb0
commit e729133134
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 14 additions and 11 deletions

3
.changelog/11482.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
api: Return a HTTP 404 instead of a HTTP 500 from the Stat File and List Files API endpoints when a file or directory is not found.
```

View File

@ -80,7 +80,7 @@ func (s *HTTPServer) DirectoryListRequest(resp http.ResponseWriter, req *http.Re
}
if rpcErr != nil {
if structs.IsErrNoNodeConn(rpcErr) || structs.IsErrUnknownAllocation(rpcErr) {
if structs.IsErrNoNodeConn(rpcErr) || structs.IsErrUnknownAllocation(rpcErr) || structs.IsErrNoSuchFileOrDirectory(rpcErr) {
rpcErr = CodedError(404, rpcErr.Error())
}
@ -120,7 +120,7 @@ func (s *HTTPServer) FileStatRequest(resp http.ResponseWriter, req *http.Request
}
if rpcErr != nil {
if structs.IsErrNoNodeConn(rpcErr) || structs.IsErrUnknownAllocation(rpcErr) {
if structs.IsErrNoNodeConn(rpcErr) || structs.IsErrUnknownAllocation(rpcErr) || structs.IsErrNoSuchFileOrDirectory(rpcErr) {
rpcErr = CodedError(404, rpcErr.Error())
}

View File

@ -177,6 +177,10 @@ func IsErrNodeLacksRpc(err error) bool {
return err != nil && strings.Contains(err.Error(), errNodeLacksRpc)
}
func IsErrNoSuchFileOrDirectory(err error) bool {
return err != nil && strings.Contains(err.Error(), "no such file or directory")
}
// NewErrRPCCoded wraps an RPC error with a code to be converted to HTTP status
// code
func NewErrRPCCoded(code int, msg string) error {

View File

@ -31,14 +31,8 @@ async function handleFSResponse(response) {
} else {
const body = await response.text();
// TODO update this if/when endpoint returns 404 as expected
const statusIs500 = response.status === 500;
const bodyIncludes404Text = body.includes('no such file or directory');
const translatedCode = statusIs500 && bodyIncludes404Text ? 404 : response.status;
throw {
code: translatedCode,
code: response.status,
toString: () => body,
};
}

View File

@ -361,7 +361,8 @@ export default function browseFilesystem({
...visitSegments({ allocation: this.allocation, task: this.task }),
path: '/what-is-this',
});
assert.equal(FS.error.title, 'Not Found', '500 is interpreted as 404');
assert.notEqual(FS.error.title, 'Not Found', '500 is not interpreted as 404');
assert.equal(FS.error.title, 'Server Error', '500 is not interpreted as 500');
await visit('/');
@ -385,7 +386,8 @@ export default function browseFilesystem({
...visitSegments({ allocation: this.allocation, task: this.task }),
path: this.directory.name,
});
assert.equal(FS.error.title, 'Not Found', '500 is interpreted as 404');
assert.notEqual(FS.error.title, 'Not Found', '500 is not interpreted as 404');
assert.equal(FS.error.title, 'Server Error', '500 is not interpreted as 404');
await visit('/');