Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this simple web server is called even number times?

Tags:

http

server

go

I'm trying to learn Go web programming, and here is a simple web server: it prints out the times being called.

package main

import (
  "fmt"
  "net/http"
)

var calls int

// HelloWorld print the times being called.
func HelloWorld(w http.ResponseWriter, r *http.Request){
    calls++
    fmt.Fprintf(w, "You've called me %d times", calls)
}

func main() {
  fmt.Printf("Started server at http://localhost%v.\n", 5000)
  http.HandleFunc("/", HelloWorld)
  http.ListenAndServe(":5000", nil)
}

When I refresh the page, I got:

You've called me 1 times
You've called me 3 times
You've called me 5 times
....

Question: Why it is 1, 3, 5 times, rather than 1,2,3...? What's the order of the function HelloWorld being called?

like image 978
Nick Avatar asked Feb 22 '16 09:02

Nick


People also ask

What is a simple web server?

In simple terms, a web server is a computer that stores, processes, and delivers website files to web browsers. Web servers consist of hardware and software that use Hypertext Transfer Protocol (HTTP) to respond to web users' requests made via the World Wide Web.

What is a web server called?

An HTTP server is software that understands URLs (web addresses) and HTTP (the protocol your browser uses to view webpages). An HTTP server can be accessed through the domain names of the websites it stores, and it delivers the content of these hosted websites to the end user's device.

What are the three types of web servers?

There are four leading web servers − Apache, IIS, lighttpd and Jagsaw. Now we will see these servers in bit more detail. Apart from these Web Servers, there are other Web Servers also available in the market but they are very expensive.

What is web server write the name of the popular web servers?

Apache HTTP server: It is the most popular web server and about 60 percent of the world's web server machines run this web server. The Apache HTTP web server was developed by the Apache Software Foundation.


1 Answers

It is because every incoming request is routed to your HelloWorld() handler function, and the browser makes multiple calls under the hood, specifically to /favicon.ico.

And since your web server does not send back a valid favicon, it will request it again when you refresh the page in the browser.

Try it with Chrome: open the Developer tools (CTRL+SHIFT+I), and choose the "Network" tab. Hit refresh, and you will see 2 new entries:

Name          Status   Type
--------------------------------------------------------
localhost     200      document
favicon.ico   200      text/plain

Since your counter starts with 0 (default value for type int), you increment it once and you send back 1. Then the request for favicon.ico increments it again (2), but the result is not displayed. Then if you refresh, it gets incremented again to 3 and you send that back, etc.

Also note that multiple goroutines can serve requests concurrently, so your solution has a race. You should synchronize access to the calls variable, or use the sync/atomic package to increment the counter safely, for example:

var calls int64

func HelloWorld(w http.ResponseWriter, r *http.Request) {
    count := atomic.AddInt64(&calls, 1)
    fmt.Fprintf(w, "You've called me %d times", count)
}

A simple "fix" to achieve what you want would be to check the request path, and if it is not the root "/", don't increment, e.g.:

func HelloWorld(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        return
    }
    count := atomic.AddInt64(&calls, 1)
    fmt.Fprintf(w, "You've called me %d times", count)
}

You may also choose to only exclude requests for favicon.ico, e.g.:

if r.URL.Path == "/favicon.ico" {
    return
}
like image 195
icza Avatar answered Oct 06 '22 18:10

icza