While creating a GET endpoint in a Spring web application I have a path variable(annotated with @PathVariable
) passed to my API.
If I don't pass any value on path, the controller responds with HTTP 404 status.
Endpoint: http://localhost:8080/observability-core/v1/systems/
If I pass a value it responds as expected (e.g http://localhost:8080/observability-core/v1/systems/123)
If the path variable is missing on the request, I want to throw HTTP 400 Bad Request to indicate something like is not passed.
PS: - when I hit request with above url I am not getting any logs implying no request reached the application. That could mean endpoint doesn't exists, which is misleading. How do I customise the error response in this case?
Default response from Spring controller endpoint:
{
"timestamp": "2024-01-04T06:48:18.584+00:00",
"status": 404,
"error": "Not Found",
"path": "/observability-core/v1/systems/"
}
My proposed solution:
@GetMapping(value = { "/path", "/path/{param}" })
required = false
(@PathVariable(required = false) String param
@RestController
@RequestMapping("/foo")
public class FooController {
@GetMapping(value = { "/{firstParam}", "/" })
public ResponseEntity<String> getFoo(@PathVariable(required = false) String firstParam) {
if (null == firstParam) {
return ResponseEntity.badRequest().body("The first param is required");
}
return ResponseEntity.ok("The first param is: " + firstParam);
}
}
A Test case:
@SpringBootTest
@AutoConfigureMockMvc
class FooControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void whenParameterIsPassesShouldReturnOk() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/foo/param"))
.andExpect(status().isOk())
.andExpect(content().string("The first param is: param"));
}
@Test
void whenParameterIsNotPassedShouldReturnBadRequest() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/foo/"))
.andExpect(status().isBadRequest())
.andExpect(content().string("The first param is required"));
}
}