preface

Recently, we used Node to do server rendering. As the middle layer, we need to request the backend interface, and we need to encapsulate the server request.

The basic use

const request = require('request')
Copy the code

The simplest way to use this package is request(URL). You can make a GET request to the specified address. From this we can see that request is exposed as a function. In fact, its internal structure is as follows

function request (uri, options, callback) {
  if (typeof uri === 'undefined') {
    throw new Error('undefined is not a valid uri or options object.')
  }

  var params = initParams(uri, options, callback)

  if (params.method === 'HEAD' && paramsHaveRequestBody(params)) {
    throw new Error('HTTP HEAD requests MUST NOT include a request body.')}return new request.Request(params)
}
Copy the code

As you can see, it accepts three functions by default, and the first parameter value must be present. There are many ways to pass parameters to request.

The parameter format

Url is mandatory and can be placed in the first argument alone or as one of the properties of option. Everything else is optional.

// Request (URL,options,callback) //letOptions = {url // Required} request(options,callback)Copy the code

shorthand

// Request. Get (URL,options,callback) // RequestletRequest. Get (options,callback) // Request. Post (URL,options,callback) // Method 2let options = {
    url
}
request.post(options,callback)
Copy the code

Why does Request support so many different ways to pass parameters? Let’s see how it’s implemented internally

The source code

As you can see from the following code, the params requirement for the final return is to include the URL request address.

functionInitParams (uri, options, callback) {// Handle options not passedif (typeof options === 'function') {
    callback = options
  }
  var params = {}
  if (typeof options === 'object') { extend(params, options, {uri: Uri}) // The passed URL will eventually be merged into pramas // and if you pass the URI in options, it will be overridden by the first parameter, which takes precedence over the first input parameter URI}else if (typeof uri === 'string') {
    extend(params, {uri: uri})
  } else{/ / deal with the first parameter is not the url of the extend (params, uri)} params. Callback = callback | | params. The callbackreturn params
}
Copy the code

Common field

Request (Options,callback) provides baseUrl to set the domain name part and the public part uniformly.

// After you define baseUrl, you just need to pass the interface APIfunction fetchPost(path,params){
  return new Promise( (resolve,reject)=>{
    request.post(path,{
      baseUrl:"http://localhost:9000/react/",},function(err, httpResponse, body){
      if(err){
        reject(err)
      }else{resolve (body)}})})} / / to use, only passed on the router interface section will eventually joining together into http://localhost:9000/react/c-request. Get ('/c-request',async ctx=>{
  let res = await fetchPost('request-header',{value:1,name:'dd'})
  ctx.body = res
})
Copy the code

Reqeust Requests and debug for different data types

To simulate the scenario where the Node server requests the back end, start two Node services, one as the requester simulation (middle tier) and the other as the back end. In addition, postman is used to initiate client requests. For data verification, vscode debug can be used or pM2 log can be enabled to verify the parameters of the request.

Let’s take a look at the setting of the request mode for different formats of POST, different from axios and fetch. Request receives different fields for different types of data requested. This can be received via body, form, and formData. Get requests are all coded in Application/X-www-form-urlencoded format, so there are no examples here.

application/x-www-form-urlencoded

The forms field takes the input parameter as follows: pass the passed parameter object directly to the form.

function fetchPost(path,params){
  return new Promise( (resolve,reject)=>{
    request.debug = true
    request.post(path,{
      form:params
    },function(err, httpResponse, body){
      if(err){
        reject(err)
      }else{
        resolve(body)
      }
    })
  })
}
Copy the code

Request has a debug mode, which is enabled with request.debug = true. To view debug messages, use pm2 start app.js –watch to start the project, and then pm2 log to view the debug messages. Red represents the logs of the middle layer and green represents the logs of the back end

The form-data file was uploaded

To pass the file through formData, use fs.createreadStream to fetch the middle layer file and send it to the back end through formData.

function fetchPost(path,params){
  return new Promise( (resolve,reject)=>{
    let formData = {
      file:fs.createReadStream(__dirname+'/.. /static/images/icon-arrow.png')
    }
    request.debug = true
    request.post(path,{
      formData
    },function(err, httpResponse, body){
      if(err){
        reject(err)
      }else{
        resolve(body)
      }
    })
  })
}
Copy the code

As you can see, the backend receives a multipart/form-data content-type. We did not manually set the request’s content-type to be automatically added.

The following code writes the received to file stream to the backend local. As you can see, icon-arrow. PNG has been successfully sent from the middle tier to the back end

application/json

Pass the argument through the body and set JSON to true, and the request automatically sets the Content-Type to Application/JSON and escapes the object passed to the body as JSON

function fetchPost(path,params){
  return new Promise( (resolve,reject)=>{
    request.debug = true
    console.log(The '*'.repeat(40));
    request.post(path,{
      baseUrl:"http://localhost:9000/react/",
      body:params,
      json:true
    },function(err, httpResponse, body){
      if(err){
        reject(err)
      }else{
        resolve(body)
      }
    })
  })
}
Copy the code

header

request.post(path,{
  form:params,
  headers:{
    // 'content-type':'application/json', / /... Any other field name:'dd',
    agent:'request'}})Copy the code

The last

Reqeust has just been used. If you have good use cases, you can share them in the comment section. If there is something worth optimizing, you can leave a message to me.