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

Shelf Response: Reason Phrase is not customizable #449

Open
JesusHdez960717 opened this issue Oct 3, 2024 · 0 comments
Open

Shelf Response: Reason Phrase is not customizable #449

JesusHdez960717 opened this issue Oct 3, 2024 · 0 comments

Comments

@JesusHdez960717
Copy link

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:
image

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:

image

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:
image

This way we have a better explanation of the response codes.

This solution clearly don't affect others status codes:

image
image
image

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant