Gzip is a compression algorithm used by the server to compress the response body and then send the response to the client to reduce the data volume and improve the transmission speed. The client obtains the original data through Gzip decompression. Additional CPU resources are consumed because of the need to compress the computation.

GzipWith HttpHeader

For compression, this behavior is negotiated between the client and the server. Only by using the same compression algorithm can the data be decoded correctly. The related headers are defined in the HTTP protocol

Content-Encoding

Is an entity message header used to compress data for a specific media type. When this header is present, its value indicates what kind of content-encoding transformation has taken place in the message body. This message header tells the client how to decode to get the media Type Content indicated in the Content-Type.

It is generally recommended to compress data as much as possible, hence the presence of this message header. But for certain types of files, such as JPEG image files, they are already compressed. Sometimes additional compression does not reduce the load volume, but may increase it.

Can be used by both the client and the server to indicate what encoding is used for the data in the body (compression algorithm)

Developer.mozilla.org/zh-CN/docs/…

Accept-Encoding

The HTTP request header accept-encoding informs (to the server) that the client understands the Encoding of the content, usually some kind of compression algorithm. With Content negotiation, the server selects a client-proposed method, which is used and notified to the client in the response header Content-Encoding.

Even if both the client and the server support the same compression algorithm, the server can choose not to compress the response body if the identity directive is accepted. There are two common situations that can lead to this:

  • The data to be sent has already been compressed and compression again will not result in a smaller amount of data being transferred. This can happen with some image files;
  • The server is overloaded and cannot handle the computing overhead caused by the compression demands. In general, If the server uses more than 80 percent of its computing power, Microsoft advises against compression.

As long as identity — which means no coding is required — is not explicitly prohibited (via identity; Q =0 instruction or *; Q =0 without explicitly specifying a weight value for identity), the server disallows returning the 406 Not Acceptable response indicating a client error.

Generally used by the client, it is shown to the server to describe the list of compression algorithms supported by the client. The service chooses one of these to compress the response body.

Developer.mozilla.org/zh-CN/docs/…

Demonstrate a manual encoding/decoding Demo

The server manually encodes Gzip

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);

	@GetMapping
	public void test(HttpServletRequest request, HttpServletResponse reponse) throws IOException {
		
		/ / response body
		String content = "You can't boast of your dirty past, but you can't boast of your dissipated past. I saw all the flowers in Changan in one day.";
		
		String acceptEncooding = request.getHeader(HttpHeaders.ACCEPT_ENCODING);
		
		/** * Gets the encoding format supported by the client. The program can use this header to determine whether to encode the response body */
		LOGGER.info(acceptEncooding);
		
		
		// The response body uses gZIP encoding
		reponse.setHeader(HttpHeaders.CONTENT_ENCODING, "gzip");
		// The response body type is a string
		reponse.setContentType(MediaType.TEXT_PLAIN_VALUE);
		// The encoding is UTF-8
		reponse.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
		// Gzip compressed response
		reponse.getOutputStream().write(gZip(content.getBytes(StandardCharsets.UTF_8)));
		
	}

	/** * Gzip compressed data *@param data
	 * @return
	 * @throws IOException
	 */
	public static byte[] gZip(byte[] data) throws IOException {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
			gzipOutputStream.write(data);
			gzipOutputStream.finish();
			returnbyteArrayOutputStream.toByteArray(); }}}Copy the code

Client manual decoding

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class Main {

	public static final Logger LOGGER = LoggerFactory.getLogger(Main.class);

	public static void main(String[] args) throws Exception {
		
		RestTemplate restTemplate = new RestTemplate();
		
		
		HttpHeaders httpHeaders = new HttpHeaders();
		What format of response body does the client support
		httpHeaders.set(HttpHeaders.ACCEPT, MediaType.TEXT_PLAIN_VALUE);
		// Accept-encoding header, indicating that the client receives gzip compression
		httpHeaders.set(HttpHeaders.ACCEPT_ENCODING, "gzip");
		
		ResponseEntity<byte[]> responseEntity = restTemplate.exchange("http://localhost/test", HttpMethod.GET, new HttpEntity<>(httpHeaders), byte[].class);
		
		if(! responseEntity.getStatusCode().is2xxSuccessful()) {// TODO non-200 response
		}

		// Get the server response body code
		String contentEncoding = responseEntity.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING);
		
		if ("gzip".equals(contentEncoding)) { / / gzip encoding
			// gzip decompresses the server response body
			byte[] data = unGZip(new ByteArrayInputStream(responseEntity.getBody()));
			
			LOGGER.info(new String(data, StandardCharsets.UTF_8));
		} else {
			// TODO other encoding}}/** * Gzip unzip *@param inputStream
	 * @return
	 * @throws IOException
	 */
	public static byte[] unGZip(InputStream inputStream) throws IOException {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		try (GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream)) {
			byte[] buf = new byte[4096];
			int len = -1;
			while ((len = gzipInputStream.read(buf, 0, buf.length)) ! = -1) {
				byteArrayOutputStream.write(buf, 0, len);
			}
			return byteArrayOutputStream.toByteArray();
		} finally{ byteArrayOutputStream.close(); }}}Copy the code

The client executes the log, decoding the response body exactly

20:36:54.129 [main] INFO - The dirty past is short, the dissipated present is long. In one day, I saw all the flowers in Changan.Copy the code

Response body compression configuration for SpringBoot

In fact, you don’t need to write the compression code for the response body yourself. Springboot provides the configuration. SpringBoot2 turns on response compression

The last

Use the RestTemplate to request the text data interface and find that the decoded string is garbled. You can wonder if the server is responding to the compressed data. To fix this, try removing the accept-Encoding request header, telling the server that the client does not need to compress the response body. If the server is still responding to the compressed data, try reading the server’s Content-Encoding header and decompressing it yourself based on the server’s compressed Encoding.

Original text: springboot. IO/topic / 286 / t…