title: How to design HTTP request Messages between two servers
body: <p>I have been learning Golang for some few months now but still find it difficult to design some applications. I have two HTTP servers A and B and would like to do the following</p>
  <ol>
  <li>server A send an HTTP PUT request with JSON body to server B.</li>
  <li>If server B is not available, server A retry until server B is up and respond to the request</li>
  <li>In server B response body is a timer value received by server A</li>
  <li>Server B uses the timer value (eg 45) to send a PATCH request using the value as interval. For example in this case, server A send the PATCH request to server B every 45 seconds.</li>
  <li>Server B respond to the PATCH request with either HTTP status code 204 or status code 404.</li>
  <li>If status code is 204, that is OK, server A continues to send the PATCH request using the 45 seconds interval.</li>
  <li>If the response status is 404, server A have to start the process again from step 1 again to step 6 when 204 status code is received.</li>
  </ol>
  <p>I have tried to write some code which works but restarting from step 1 when 404 status code is received is my problem now in the PATCHMessage function below when the status code is 404 or NotFound. Also am not sure if my application design is good enough. Any help and comments about my application design. What would be the best way to design this steps if what i did below is not the best approach. Below is my code</p>
  <pre><code>
  var (
      ContentLocation string
      Timer  int32
      mu      sync.Mutex
  )
  
  func SendPUTMessageToServerB() {
      
      msgbytes, err := ioutil.ReadFile(&quot;./msg.json&quot;)
      ...
  
      locProfilebytes, err := json.Marshal(pcfprofile)
    ...
   
      locVarNRFUrl := &quot;server B url&quot;
  
      profile, resp, err := HandlePUTMessage(locProfilebytes, locVarNRFUrl)
  
      status := resp.StatusCode
      
      if status == http.StatusOK {
          logrus.Println(&quot;PUT mesage Update SUCCESS&quot;)
      } else if status == http.StatusCreated {
          logrus.Println(&quot;PUT message SUCCESS&quot;)
      } else {
  
          logrus.Println(fmt.Errorf(&quot;Wrong status code returned by server B %d&quot;, status))
      }
  
      ContentLocation = resp.Header.Get(&quot;Location&quot;)
      Timer = profile.TimerValue
  }
  
  func HandlePUTMessage(filebyte []byte, VarPath string) (Profile, *http.Response, error) {
  
      var (
          // Set client and set url
          localVarHTTPMethod = http.MethodPut
          nfp          Profile
      )
  
      req, err := http.NewRequest(localVarHTTPMethod, VarPath, bytes.NewBuffer(filebyte))
      if err != nil {
          logrus.Error(err)
      }
      req.Close = true
      req.Header.Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
  
      backoff := 1
      for {
          res, err := Client.Do(req) 
          if err != nil || res == nil {
              logrus.Println(&quot;Server A Trying to send PUT request ...&quot;)
              backoff *= 2
              if backoff &gt; 20 {
                  backoff = 20
              }
              time.Sleep(time.Duration(backoff) * time.Second)
              continue
          }
  
          defer func() {
              if resCloseErr := res.Body.Close(); resCloseErr != nil {
                  logrus.Errorf(&quot;Response body cannot close: %+v&quot;, resCloseErr)
              }
          }()
  
          bodybytes, err := ioutil.ReadAll(res.Body)
          //localVarHTTPResponse.Body.Close()
          if err != nil {
              logrus.Error(err)
              return nfp, res, err
          }
  
          json.Unmarshal(bodybytes, &amp;nfp)
          return nfp, res, nil
      }
  }
  
  // Send PATCH message to server B 
  func PATCHMessage() (err error) {
   ...
  
      patchitembytes, err := json.Marshal(patchitem)
  
      ...
  
      req, err := http.NewRequest(&quot;PATCH&quot;, ContentLocation, bytes.NewBuffer(patchitembytes))
      req.Header.Set(&quot;Content-Type&quot;, &quot;application/json-patch+json&quot;)
      
      response, err := transport.Client.Do(req) // for dev
  
      defer response.Body.Close()
  
      status := response.StatusCode
      if status == http.StatusNoContent {
          
              logrus.Info(&quot;PATCH message SUCCESS&quot;)
      } else if status == http.StatusNotFound {
  
          // Here I would like to restart PUT message if status code is 404
          
          logrus.Println(&quot;Heart-Beat Message FAILED&quot;) 
      }
      return err
  }
  
  // Send a patch message every Timer value
  func SendPATCHMessageEveryTimerValue() {
  
      for {
          ticker := time.NewTicker(time.Duration(Timer) * time.Second)
          mu.Lock()
  
          for _ = range ticker.C {
              err := PATCHMessage()
              if err != nil {
                  SendPUTMessage()
              }
          }
          mu.Unlock()
      }
  }
  
  
  func main() {
  
      SendPUTMessageToServerB()
      go SendPATCHMessageEveryTimerValue()
  }
  
  </code></pre>