Respond with 404 Not Found if project not found in Api::SchoolProjectsController actions #564
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Previously when a request was made to either of the actions in
Api::SchoolProjectsController
for a project that does not exist, the following exception was raised, because the call toProject.find_by
returnednil
:Unhandled exceptions are rescued by the default
ActionDispatch::ShowExceptions
middleware. In turn this uses the default exceptions app,ActionDispatch::PublicExceptions
to render a static HTML error page frompublic/500.html
in this case.Since this is an API endpoint, ideally it should always respond with JSON in the response body, otherwise it makes writing client code a lot harder. Indeed my actual motivation for fixing this is, because we've been seeing
JSON:ParseError
exceptions raised in experience-cs.I've fixed the problem by using
Project.find_by!
instead ofProject.find_by
. This means that if the project is not found, aActiveRecord::RecordNotFound
exception is raised. This in turn is rescued by therescue_from
block inApiController
and the action responds with a404 Not Found
head response, i.e. with no body.This head response seems to be handled OK by the HTTParty code in experience-cs and thus it fixes the problem I was trying to address.
The equivalent client-side code in editor-standalone was already throwing an
AxiosError
exception due to the500
response code (not being a2XX
code) and it will continue to throw the same exception, albeit with a payload reflecting the response code being404
instead of500
and the body being empty instead of being the Rails500
HTML error page.There is no specific error-handling code in editor-standalone catching this exception, so I assume it's just relying on the generic error handling for the React app. Thus I think the user-facing behaviour should be unchanged.
Addresses https://github.com/RaspberryPiFoundation/experience-cs/issues/828.
Postscript
While investigating this issue, I've uncovered a number of other problems with the
Api::SchoolProjectsController
code and its specs, but I've intentionally not addressed them here in order to keep the scope of this PR as small as possible and keep it focussed on fixing the problem at hand. However, in case it's useful, I'll list the issues here:load_and_authorize_resource :project
is not working as intended:Project
instance (even if it was, it would be attempting to callProject.find(params[:id)
and notProject.find_by!(identifier: params[:id]
)Project
(it seems to be authorizing the user canshow
theProject
class, but it seems unlikely this is what was intended)load_and_authorize_resource
was added and no tests fail if I remove it!Api::ProjectsController
uses a customProjectLoader
class which takeslocale
into account, I would've thought that thisApi::SchoolProjectsController
should also use the same lookup mechanism, but it doesn't.before_action :authorize_user
call.ProfileApiMock#stub_profile_api_list_school_students
inspec/requests/school_projects/show_finished_spec.rb
&spec/requests/school_projects/set_finished_spec.rb
seem unnecessary and are potentially confusing. This helper method stubsProfileApiClient.list_school_students
, but this method is never called by code exercised by those specs. This seems to be a wider problem where calls toProfileApiMock#stub_profile_api_list_school_students
have been added to specs that don't need it. Perhaps they never needed it or the need for them has gone away.lib/concepts/*/operations/
are usually rescued and the action responds with a JSON body. However, for exceptions that occur outside those operations (e.g. in the actions themselves) just result in the 500 error with HTML body.