introduce

In a development scenario where the front and back end are separated, it is inevitable that there will be front and back end tuning. In the debugging stage, we often encounter various problems, such as garbled code, data (string, array, Json object) transmitted from the front end cannot be properly parsed at the back end, etc. This paper hopes to start from the source, clarify the root cause of the problem, quickly locate the location of the problem, so that the front and back end of the joint adjustment handy, so that the pot is no longer so easy……

The HTTP protocol

The HTTP protocol is introduced here because HTTP is indispensable for front-end and back-end tuning. Understanding the HTTP protocol helps to better understand the data transmission process and better analyze the problem in the end, so as to facilitate troubleshooting.

1. Introduction

First, HTTP is a stateless protocol, meaning that every client and server interaction is stateless, often using cookies to maintain state. The following diagram shows the rough structure of HTTP requests and responses (this part of the allocation diagram is from the AUTHORITATIVE HTTP Guide) :

Note: As you can see from the figure above, the HTTP request is roughly divided into three parts: the start line, the header, and the body. In the request start line, the request method, request address, and HTTP protocol version are displayed. In addition, the header is what we call the HTTP header.

2. HTTP method

The following are common HTTP request methods and their introduction:

Description:

  1. We usually use get and POST.
  2. Include body means whether the request content has a body. For example, in get mode, the parameters can only be passed in THE URL mode because there is no body.

3. Content-type

The Content Type and encoding of HTTP transfers are controlled by the Content-Type, which is used by clients and servers to identify and parse the transferred Content.

Common content-type:

type instructions
text/html HTML type
text/css The CSS file
text/javascript Js file
text/plain Text file
application/json Json type
application/xml XML type
application/x-www-form-urlencoded Form, the default type for form submission
multipart/form-data Attachment type, usually form file upload

The first six are common file types, and the last two are form data submission types. When we submit ajax data, we usually do content-Type :application/ X-www-form-urlencoded; Charset = UTF-8, which specifies the data format and data encoding mode of this request. It should be added that application/ X-www-form-urlencoded is a special type, when data is sent, form data will be stitched into a format similar to A = 1&B =2&c=3, and if there are Spaces or special characters in data, conversion will be done. The standard document is here. More details are available in [RFC1738].

Related information:

  1. Content-type mapping table: tool.oschina.net/commons
  2. Form Content Types: www.w3.org/TR/html4/in…
  3. Character decoding plus decoding for space problem to explore: muchstudy.com/2017/12/06/…
  4. Content-type: Homeway. me/2015/07/19/… content-Type: Homeway. me/2015/07/19/…

4. Character sets and encoding

The reason why we need to understand this part is that in the data interaction between the front and back ends, we often encounter the problem of garbled code. Knowing this content, it is easy to solve the problem of garbled code.

A picture is worth a thousand words:

In the figure, the value of Charset is ISO-8859-6, which details a complete process of text encoding, decoding, and display.

Related information:

  1. Character set list: www.iana.org/assignments…
  2. A character encoding a: muchstudy.com/2016/08/26/…

The front part

The front-end part is responsible for initiating HTTP requests, and the commonly used FRONT-END HTTP request tool classes include jquery, AXIOS and FETCH. In fact, both jquery and AXIOS use XMLHttpRequest at the bottom to initiate HTTP requests. Fetch belongs to the browser’s built-in method of initiating HTTP requests.

Example front-end Ajax request:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.5.1/qs.min.js"></script>
<title>An example of sending HTTP requests from the front-end</title>
</head>
<body>
	<h2>Using XMLHttpRequest</h2>
	<button onclick="xhrGet()">XHR Get</button>
	<button onclick="xhrPost()">XHR Post</button>
	<h2>Using axios</h2>
	<button onclick="axiosGet()">Axios Get</button>
	<button onclick="axiosPost()">Axios Post</button>
	<h2>Using the fetch</h2>
	<button onclick="fetchGet()">Fetch Get</button>
	<button onclick="fetchPost()">Fetch Post</button>
	<script>
		// Encapsulate XMLHttpRequest to initiate an Ajax request
		let Axios = function({url, method, data}) {
	        return new Promise((resolve, reject) = > {
	            var xhr = new XMLHttpRequest();
	            xhr.open(method, url, true);
	            xhr.onreadystatechange = function() {
	                // readyState == 4 Indicates that the request is complete
	                if (xhr.readyState == 4 && xhr.status == 200) {
	                    // Get data from the server
	                    resolve(xhr.responseText)
	                }
	            };
	            if(data){
	            	xhr.setRequestHeader('Content-type'.'application/x-www-form-urlencoded; charset=utf-8');
	            	xhr.send(Qs.stringify(data));
	            	//xhr.send("a=1&b=2");
	            	//xhr.send(JSON.stringify(data));
	            }else{ xhr.send(); }})}// Data to post
		let postData = {
	    	firstName: 'Fred'.lastName: 'Flintstone'.fullName: 'name'.arr: [1.2.3]}// Request an address
		let url = 'DemoServlet';

		function xhrGet(){
			Axios({
				url: url+'? a=1'.method: 'GET'
			}).then(function (response) {
		    	console.log(response); })}function xhrPost(){
			Axios({
				url: url,
				method: 'POST'.data: postData
			}).then(function (response) {
		    	console.log(response); })}function axiosGet(){
			// Default content-type = null
			axios.get(url, {
				params: {
		      		ID: '12345'
		      	}
		  	}).then(function (response) {
		    	console.log(response);
			}).catch(function (error) {
			    console.log(error);
			});
		}
		function axiosPost(){
			// Default content-type = application/json; charset=UTF-8
			axios.post(url, postData).then(function (response) {
		    	console.log(response);
		  	}).catch(function (error) {
		    	console.log(error);
		  	});
		  	// Default content-type = application/x-www-form-urlencoded
			axios({
			  method: 'post'.url: url,
			  data: Qs.stringify(postData)
			}).then(function (response) {
		    	console.log(response);
		  	});
		}

		function fetchGet(){
			fetch(url+'? id=1').then(res= > res.text()).then(data= > {
				console.log(data)
			})
		}
		function fetchPost(){
			fetch(url, {
			    method: 'post'.body: postData
			  })
			  .then(res= > res.text())
			  .then(function (data) {
			    console.log(data);
			  })
			  .catch(function (error) {
			    console.log('Request failed', error);
			  });
		}
	</script>
</body>
</html>

Copy the code

Related information:

  1. XMLHttpRequest Standard:xhr.spec.whatwg.org/
  2. The Fetch Standard:fetch.spec.whatwg.org/
  3. Introduction to XMLHttpRequest: developer.mozilla.org/zh-CN/docs/…
  4. The fetch is introduced: developers.google.com/web/updates…
  5. Fetch Introduction: The next generation of Ajax APIS: juejin.cn/post/684490…
  6. Axios source: github.com/axios/axios

The backend part

Here we use the Java platform as an example to show how the back end receives HTTP requests. In J2EE system, data receiving and returning are actually done by Servlet.

Example servlets receive and return data:

package com.demo.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DemoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public DemoServlet(a) {
		super(a); }protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("-----------------start----------------");
		System.out.println("Content-Type:" + request.getContentType());
		// Prints the request parameters
		System.out.println("========= request parameters ========");
		Enumeration<String> em = request.getParameterNames();
		while (em.hasMoreElements()) {
			String name = (String) em.nextElement();
			String value = request.getParameter(name);
			System.out.println(name + "=" + value);
			response.getWriter().append(name + "=" + value);
		}
		// From inputStream
		System.out.println("===========inputStream===========");
		StringBuffer sb = new StringBuffer();
		String line = null;
		try {
			BufferedReader reader = request.getReader();
			while((line = reader.readLine()) ! =null)
				sb.append(line);
		} catch (Exception e) {
			/* report an error */
		}
		System.out.println(sb.toString());
		System.out.println("-----------------end----------------");
		response.getWriter().append(sb.toString());
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException { doGet(request, response); }}Copy the code

Related information:

  1. What is the nature of servlets and how does it work? : www.zhihu.com/question/21…
  2. How does Tomcat handle HTTP requests? : blog.csdn.net/qq_38182963…

The results summary

Request way method Request the content-type The data format The content-type received by the backend Whether to get data using getParameter Whether data can be retrieved through inputStream Back-end receive type
XHR Get Is not set Url and the cords null can no Key/value pair
XHR Post Is not set Json string text/plain; charset=UTF-8 no can string
XHR Post Is not set A =1&b=2 format string text/plain; charset=UTF-8 no can string
XHR Post application/x-www-form-urlencoded A =1&b=2 format string application/x-www-form-urlencoded can no The back end receives key-value pairs with keys A and B and values 1 and 2
XHR Post application/x-www-form-urlencoded Json string application/x-www-form-urlencoded can no The back end receives a key-value pair with json data key and null value
axios Get Is not set Url and the cords null can no Key/value pair
axios Post Is not set Json object application/json; charset=UTF-8 no can Json string
axios Post Is not set An array of application/json; charset=UTF-8 no can Array string
axios Post Is not set A =1&b=2 format string application/x-www-form-urlencoded can no Key/value pair
fetch Get Is not set Url and the cords null can no Key/value pair
fetch Post Is not set A =1&b=2 format string text/plain; charset=UTF-8 no can A = 1 & b = 2 a string
fetch Post Is not set Json object text/plain; charset=UTF-8 no can The back end receives the string [Object object]
fetch Post application/x-www-form-urlencoded; charset=UTF-8 A =1&b=2 format string application/x-www-form-urlencoded; charset=UTF-8 can no Key/value pair

As can be seen from the table above, any data sent using get or Content-type as Application/X-www-form-urlencoded will be converted to key-value pairs by default in back-end servlets. Otherwise, string data sent from the front end is retrieved from the input stream and converted into Java entity classes or collection objects using a back-end utility class such as fastJSON.

Syndication tool Postman

The Postman plugin can be downloaded from chrome’s App Store to simulate HTTP requests in the browser. The Postman interface looks like this:

Description:

  1. To send a GET request, simply add parameters to the URL and click Send
  2. To send a POST request, data can be transmitted in three ways;form-data,x-www-form-urlencoded,raw(unprocessed)
type Content-Type instructions
form-data Content-Type: multipart/form-data The attachment submission method of the form
x-www-form-urlencoded Content-Type: application/x-www-form-urlencoded The post submission method of the form
raw Content-Type: text/plain; charset=UTF-8 How the text is submitted