Сообщение Как в Spring Boot включить Content-Length в ответ? от 06.05.2022 10:01
Изменено 06.05.2022 10:54 Worminator X
Как в Spring Boot включить Content-Length в ответ?
Разрабатываю онлайн-игру с сервером на Java и клиентом на Си. Для передачи данных используется REST + XML (Jackson). Клиент подключается к серверу через TCP сокет, отправляет HTTP-запросы, парсит тело из ответа с помощью Expat'а и обновляет картинку. На сервере используется обычное Spring Boot приложение со встроенным Jetty.
Проблема в том, что по умолчанию Spring Boot использует Transfer-Encoding с разбиением ответа на chunk'и. Возвращаемые заголовки в ответе:
Вот пример контроллера Spring:
На StackOverflow пишут, что это Spring таким образом использует сжатие ответа. Хорошо, в файле конфигурации application.yml отключаю его:
Не помогает, все равно ответ возвращается с Transfer-Encoding: chunked. Как исправить?
Проблема в том, что по умолчанию Spring Boot использует Transfer-Encoding с разбиением ответа на chunk'и. Возвращаемые заголовки в ответе:
Естественно, читать такой ответ, собирая из кусков, неудобно и очень медленно. Как из заголовков убрать Transfer-Encoding: chunked и соответственно добавить Content-Length с указанием размера данных, чтобы тело шло единым набором байтов, который сразу можно было бы прочитать?Content-Type: application/xml
Date: Fri, 06 May 2022 09:41:32 GMT
Transfer-Encoding: chunked
Вот пример контроллера Spring:
@RestController
@RequestMapping("/users")
public class UsersController {
@GetMapping(value = "/")
public List<User> getAllUsers() {
return UsersService.getInstance().findAll();
}
@GetMapping(value = "/{id}")
public ResponseEntity<User> getUser(@PathVariable String id) {
final Optional<User> user = UsersService.getInstance().find(id);
return user.isPresent() ?
ResponseEntity.ok().contentType(MediaType.APPLICATION_XML).body(user.get()) :
ResponseEntity.notFound().build();
}
}
На StackOverflow пишут, что это Spring таким образом использует сжатие ответа. Хорошо, в файле конфигурации application.yml отключаю его:
server:
compression:
enabled: false
port: 2992
Не помогает, все равно ответ возвращается с Transfer-Encoding: chunked. Как исправить?
Как в Spring Boot включить Content-Length в ответ?
Разрабатываю онлайн-игру с сервером на Java и клиентом на Си. Для передачи данных используется REST + XML (Jackson). Клиент подключается к серверу через TCP сокет, отправляет HTTP-запросы, парсит тело из ответа с помощью Expat'а и обновляет картинку. На сервере используется обычное Spring Boot приложение со встроенным Jetty.
Проблема в том, что по умолчанию Spring Boot использует Transfer-Encoding с разбиением ответа на chunk'и. Возвращаемые заголовки в ответе:
Вот пример контроллера Spring:
На StackOverflow пишут, что это Spring таким образом использует сжатие ответа. Хорошо, в файле конфигурации application.yml отключаю его:
Не помогает, все равно ответ возвращается с Transfer-Encoding: chunked. Как исправить?
UPD Работает, если задать Content-Length в контроллере вручную через метод ReponseEntity:
Но это костыль и быдлокод, 2 раза выполяется сериализация для объекта. Очевидно, Spring должен рассчитывать его автоматически. Как это сделать?
Проблема в том, что по умолчанию Spring Boot использует Transfer-Encoding с разбиением ответа на chunk'и. Возвращаемые заголовки в ответе:
Естественно, читать такой ответ, собирая из кусков, неудобно и очень медленно. Как из заголовков убрать Transfer-Encoding: chunked и соответственно добавить Content-Length с указанием размера данных, чтобы тело шло единым набором байтов, который сразу можно было бы прочитать?Content-Type: application/xml
Date: Fri, 06 May 2022 09:41:32 GMT
Transfer-Encoding: chunked
Вот пример контроллера Spring:
@RestController
@RequestMapping("/users")
public class UsersController {
@GetMapping(value = "/")
public List<User> getAllUsers() {
return UsersService.getInstance().findAll();
}
@GetMapping(value = "/{id}")
public ResponseEntity<User> getUser(@PathVariable String id) {
final Optional<User> user = UsersService.getInstance().find(id);
return user.isPresent() ?
ResponseEntity.ok().contentType(MediaType.APPLICATION_XML).body(user.get()) :
ResponseEntity.notFound().build();
}
}
На StackOverflow пишут, что это Spring таким образом использует сжатие ответа. Хорошо, в файле конфигурации application.yml отключаю его:
server:
compression:
enabled: false
port: 2992
Не помогает, все равно ответ возвращается с Transfer-Encoding: chunked. Как исправить?
UPD Работает, если задать Content-Length в контроллере вручную через метод ReponseEntity:
@RestController
@RequestMapping("/users")
public class UsersController {
@GetMapping(value = "/")
public List<User> getAllUsers() {
return UsersService.getInstance().findAll();
}
@GetMapping(value = "/{id}")
public ResponseEntity<User> getUser(@PathVariable String id) {
final Optional<User> user = UsersService.getInstance().find(id);
return user.isPresent() ?
ResponseEntity.ok().contentType(MediaType.APPLICATION_XML).contentLength(
getContentLength(user.get())
).body(user.get()) :
ResponseEntity.notFound().build();
}
private static long getContentLength(User user) {
try {
final XmlMapper mapper = new XmlMapper();
final String xml = mapper.writeValueAsString(user);
return xml.length();
} catch (JsonProcessingException ex) {
return 0;
}
}
}
Но это костыль и быдлокод, 2 раза выполяется сериализация для объекта. Очевидно, Spring должен рассчитывать его автоматически. Как это сделать?