Description
When we return a response with a status like 422, the reason phrase is empty and no details are specified.
This is the example to reproduce it:
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
void main() async {
var handler =
const Pipeline().addMiddleware(logRequests()).addHandler(_echoRequest);
var server = await shelf_io.serve(handler, 'localhost', 8080);
// Enable content compression
server.autoCompress = true;
print('Serving at http://${server.address.host}:${server.port}');
}
Response _echoRequest(Request request) => Response(422);
When making the request in postman it looks like this:
When we create the same service in other framework, like spring for example, the response is more explained like this.
Having this example:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@RestController
public static class TestController {
@GetMapping("/")
public ResponseEntity close() {
return new ResponseEntity(HttpStatusCode.valueOf(422));
}
}
}
This give us a more explained response like this:
Looking a little deeper, the HttpResponse
class (from the http lib), has the reason phrase parameter to be set. However the Response
class (from shelf) does not have this property to be configured. And of course, in the _writeResponse
of the shelf_io
the mapping to said property is not done.
Fixing this is as easy as adding the property 'reasonPhrase' to the Response
and later mapping it to HttpResponse
:
/// The response returned by a [Handler].
class Response extends Message {
/// The HTTP status code of the response.
final int statusCode;
/// THIS PROPERTY IS THE ONE TO ADD
/// The reason phrase for the response.
///
/// If no reason phrase is explicitly set, a default reason phrase is provided.
final String? reasonPhrase;
///(AL THE OTHER STUFF IN THE CLASS)
/// Constructs an HTTP response with the given [statusCode].
///
/// [statusCode] must be greater than or equal to 100.
///
/// {@macro shelf_response_body_and_encoding_param}
Response(
this.statusCode, {
this.reasonPhrase, //ADDED reason phrase param
Object? body,
Map<String, /* String | List<String> */ Object>? headers,
Encoding? encoding,
Map<String, Object>? context,
}) : super(body, encoding: encoding, headers: headers, context: context) {
if (statusCode < 100) {
throw ArgumentError('Invalid status code: $statusCode.');
}
}
And also we need to added in write function:
Future<void> _writeResponse(
Response response, HttpResponse httpResponse, String? poweredByHeader) {
if (response.context.containsKey('shelf.io.buffer_output')) {
httpResponse.bufferOutput =
response.context['shelf.io.buffer_output'] as bool;
}
httpResponse.statusCode = response.statusCode;
httpResponse.reasonPhrase = response.reasonPhrase ?? ''; ///NEW LINE TO ADD IN ORDER TO SET UP PROPERTY
// An adapter must not add or modify the `Transfer-Encoding` parameter, but
// the Dart SDK sets it by default. Set this before we fill in
// [response.headers] so that the user or Shelf can explicitly override it if
// necessary.
httpResponse.headers.chunkedTransferEncoding = false;
(MORE STUFF OF METHOD)
Whit this couple of changes when we run the same example it give us the following response:
This way we have a better explanation of the response codes.
This solution clearly don't affect others status codes:
Would this be a worthy feature to add to the package to create a PR?
Or was it designed this way specifically for some reason?
Thanks in advance